Reflection Go:reflect:Call的输入参数太少
我遇到了使用反射库的问题。我想用它是因为有很多建议,但我只是在学习围棋,有些地方并不容易 我有这部分代码:Reflection Go:reflect:Call的输入参数太少,reflection,go,Reflection,Go,我遇到了使用反射库的问题。我想用它是因为有很多建议,但我只是在学习围棋,有些地方并不容易 我有这部分代码: func countDataByName(sourceName string, statData interface{}, filters Filter, chartName string) []ChartElement { ... //step 1 - filter filteredData := reflect.ValueOf(statData
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,输入参数太少
。但是如果我在reflect.ValueOf(&statData)
上更改reflect.ValueOf(statData)
,则错误为reflect:call of reflect.Value.call on zero Value
statData
提供了两种类型中的一种,对于这两种类型,我有如下结构和方法:
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)
}
...
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
这个Println也不起作用。上面的代码恐慌,方法未被触发。我的错在哪里
Upd 1:
发现如果我在我要调用的function中删除paramdata
,它会很好地调用。但是
我有statData
作为一行结构,所以类型是NoaggModel
。在方法FilterData
中,我得到这1行作为ng
。但我需要将其更改为[]NoaggModel
。在这种情况下,如何调用reflect
,以及如何将参数传递给filter函数
Upd 2:
我修改了几个部分:
func (ng *NoaggModel) FilterData(filter interface{}, data NoaggModel) {
fmt.Println("data : ",ng)
}
在这里,如果在revel controller中设置了正确的类型,并且方法在模型中,则如何将正确的类型传递给过滤器。或者我应该在每个模型中设置类型并在控制器中调用它
我在《控制器》中写道:
//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
是NoaggModel类型的一行,但我得到了错误:
reflect: Call using *models.NoaggModel as type models.NoaggModel
类型也是由上面代码中的reflect
设置的,如下所示:
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)
}
...
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
根据映射动态创建类型实例,这在您不知道可能需要处理哪些类型时非常有用。但是在你的情况下,你应该考虑使用接口。
虽然我真的不知道您想要实现什么,但我建议您首先创建一个所有模型都需要实现的接口(修改它以满足您的需要):
NoaggModel
和OracleModel
将通过定义类似的方法来实现上述接口:
func (ng *NoaggModel) FilterData(filter interface{}) {
fmt.Printf("data: %#v, filter: %#v\n", ng, filter)
}
然后,将反序列化数据
(和statData
)更改为接口类型模型
,而不是接口{}
。由于只有两种类型,因此可以通过使用开关来避免使用反射:
...
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:Call,使用*models.NoaggModel作为类型models.NoaggModel
。我将更新我的问题,了解详细信息Elem()
帮助取消reflect.Values中的指针引用,这可能会有所帮助。也不了解您试图做的事情,但我高度怀疑是否需要反射。接口应该做到这一点。我正在尝试在一些结构类型之间切换,并根据传入的字符串参数从正确的接口调用方法。我有一些用于数据源的接口,这些数据必须以不同的方式进行过滤和计数。所以我需要获取缓存,将其放入结构,并从不同的接口调用相同的方法。我描述了在调用缓存之前进行类型断言,因此我创建了一个interface{}
类型的变量,将类型断言为所需的类型,获取缓存并尝试使用反射调用方法。我将方法的名称命名为字符串。这看起来非常漂亮和清晰。说到种类的数量,现在只有两种。在使用的几个月内,用量将不断增加。该应用程序将采用其他数据源,这类数据的列表将不断增加。同时,我确信列表不会超过30-40。但是,如果我重写代码,为了避免使用反射,我如何通过字符串名调用接口的方法,该字符串名作为参数来自POST
。过滤数据后的每种类型(oracleModel
,NoaggModel
)都必须以不同的方式计数。所以我计划为每个接口创建方法,并按名称调用它们。如果不使用reflect,我需要对方法名进行切片或映射,并从映射中按名称调用它们?@Altenrion您还可以对methodName
使用开关方法名{case“filterData”:反序列化数据。filterData(filter)}
。如果不是所有模型都实现所有方法?那么,您可以为每个方法创建一个接口,并尝试创建一个接口来检查模型类型是否实现了特定的方法。例如:OracleModel(countByX,countByY),NoaggMoldel(countByZ,countByS),我想以集中的方式保存,以避免大量的切换,并有或多或少的安全代码,以避免运行时errors@Altenrion试图理解的另一个尝试:)不使用不同的方法怎么样OracleModel.Count(ax,by)
和NoaggModel.Count(az,bs)
,但是您可以使用方法Count(a接口{},b接口{})结果的接口
。然后,每个模型的计数方法将处理a
和b
的断言,以键入X
/Y
或Z
/s
?