簡體   English   中英

執行:反射:使用很少的輸入參數進行調用

[英]Go: reflect : Call with too few input arguments

我一直堅持使用反射庫的問題。 我建議使用它,因為有很多建議,但是我只是在學習go,而某些部分並不是很容易。

我有這部分代碼:

 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
 }

如果執行這樣的方法,則會出現錯誤: reflect: Call with too few input arguments 但是,如果我更改了reflect.ValueOf(&statData) reflect.ValueOf(statData)上的reflect.ValueOf(&statData) ,那么錯誤就是reflect: call of reflect.Value.Call on zero Value

statData帶有2種類型之一,在這種類型之前,我有結構和方法,例如:

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)
}

此Println也不起作用。 上面的代碼恐慌,未觸發方法。 我的錯在哪里?

更新1:

發現,如果我刪除了要調用的函數中的參數data ,那么調用起來就好了。 但! 我將statData作為結構的1行,因此類型為NoaggModel 在方法FilterData我將此第1行作為ng 但是我需要將其更改為[]NoaggModel 在這種情況下如何調用reflect以及如何將參數傳遞給過濾器函數?

更新2:我修改了一些部分:

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

在這里,如何將正確的類型傳遞給filter ,如果它是在發布控制器中設置的,並且方法在模型中。 還是應該在每個模型中設置類型並在控制器中調用它?

在控制器中,我寫道:

//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)

StatDataStatData類型的行,但出現錯誤:

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

該類型也是通過在上面的代碼中reflect來設置的,如下所示:

    ...
    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

反思並不容易。 並且應盡可能避免。

我承認我確實建議使用reflect來基於地圖動態創建類型的實例,當您不知道可能需要處理哪些類型時,這真的很有用。 但是在您的情況下,您應該考慮使用接口。

雖然我真的不知道要實現什么,但我建議從創建一個所有模型都需要實現的接口開始(進行修改以適應您的需求):

type Model interface {
    FilterData(interface{})
}

然后, NoaggModelOracleModel將通過定義類似的方法來實現上述接口:

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

然后,切換deserializedData (和statData )是接口類型的Model ,而不是interface{} 並且由於只有兩種類型,因此可以通過使用開關來避免使用反射:

...
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")

無需導入reflect

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM