duanji5746 2016-02-16 09:53
浏览 75
已采纳

执行:反射:使用很少的输入参数进行调用

I've stucked with problems of using reflect library. I descided to use it because of many recomendations, but i'm just learning go and some parts are not really easy..

I've got this part of code :

 func countDataByName(sourceName string, statData interface{}, filters Filter, chartName string) []ChartElement {
            ...
    //step 1 - filter
    filteredData := reflect.ValueOf(statData).MethodByName("FilterData").Call([]reflect.Value{})

    //step 2 - cluster
    //  clusterData := reflect.ValueOf(filteredData).MethodByName("clusterData").Call([]reflect.Value{})

    //step 3 - count
    //  countedData := reflect.ValueOf(clusterData).MethodByName(chartName).Call([]reflect.Value{})

    fmt.Println("Never prints to anywhere", filteredData)

            ...
     return filterData
 }

If I execute the method like this, I get error : reflect: Call with too few input arguments. But if I change reflect.ValueOf(statData) on reflect.ValueOf(&statData) than error is reflect: call of reflect.Value.Call on zero Value

statData comes with one of 2 types, and fore this types I have structs and methods, like this :

type NoaggModel struct {
    Date             string
    Hour             int
    Id_user          int
    Id_line          int
    Id_region        int
    Id_tree_devision int
    N_inb            int
    N_inb_d          int
    T_ring           int
    T_inb            int
    T_inb_d          int
    T_hold           int
    T_acw            int
    T_acw_d          int
    T_wait           int
}

func (ng *NoaggModel) FilterData( data NoaggModel) {
    fmt.Println("FilterData")
    fmt.Println("data : ", data)
}

this Println also not works. Code panics above , and method was not triggered. Where is my mistake here?

Upd 1:

Found that if I remove param data in functioin that I want to call, than it calls nicely. But! I have statData as 1 row, of structs, so type is NoaggModel. And in the method FilterData I get this 1 row as ng. But I need to change it to the []NoaggModel. How to call reflect in this case and how to pass parameter to the filter function ?

Upd 2: I modified few parts :

func (ng *NoaggModel) FilterData(filter interface{}, data NoaggModel) {
    fmt.Println("data : ",ng)
}

In here, how to pass correct type to filter, if it is set up in revel controller, and method is in model. Or should I set the type in each model and call it in controller?

And in controller I wrote :

//step 1 - filter
    in := make([]reflect.Value, 2)

    in[0] = reflect.ValueOf(filters)
    in[1] = reflect.ValueOf(statData)

    filteredData := reflect.ValueOf(statData).MethodByName("FilterData").Call(in)

StatData is a row of type NoaggModel, but I get the error :

 reflect: Call using *models.NoaggModel as type models.NoaggModel 

The type was set also by reflect in code above, like this :

    ...
    var sourceTypes = map[string]reflect.Type{
        "noagg": reflect.TypeOf(models.NoaggModel{}),
        "oracle": reflect.TypeOf(models.OracleModel{}),
    }
    deserializedData = reflect.New(sourceTypes[sourceName]).Interface()
    ...
    // deserialised becomes statData
  • 写回答

1条回答 默认 最新

  • duanqiao9541 2016-02-16 13:56
    关注

    Reflection is not easy. And should be avoided if possible.

    I admit that I did recommend using reflect to dynamically create instances of types based on a map, which is really useful when you don't know which types you might have to handle. But in your case you should consider using interfaces.

    While I don't really know what you want to achieve, I would suggest starting by creating an interface that all your Models need to implement (modify it to fit your needs):

    type Model interface {
        FilterData(interface{})
    }
    

    NoaggModel and OracleModel would then implement the above interface by defining similar methods like this:

    func (ng *NoaggModel) FilterData(filter interface{}) {
        fmt.Printf("data: %#v, filter: %#v
    ", ng, filter)
    }
    

    Then, change deserializedData (and statData) to be of the interface type Model instead of interface{}. And since you only have two types, you can avoid using reflect by having a switch instead:

    ...
    var deserializedData Model
    
    switch sourceName {
    case "noagg":
        deserializedData = new(models.NoaggModel)
    case "oracle":
        deserializedData = new(models.OracleModel)
    }
    ...
    // Marshal the values into deserializedData which now holds an instance of the desired type
    ...
    deserializedData.FilterData("Replace this string with your filter")
    

    And it is done without having to import reflect!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作