[英]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)
StatData
是StatData
类型的行,但出现错误:
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{})
}
然后, NoaggModel
和OracleModel
将通过定义类似的方法来实现上述接口:
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.