3 回答
TA贡献1842条经验 获得超21个赞
您的函数不能通过名称引用自身,因为它是一个匿名函数。它只有在分配给变量后才会被命名lookup。从词法上讲,这仅在分配的值被完全解析后才会发生。这与普通func声明不同,后者的名称立即可用(这使得递归更加简洁):
func myFunc(arg) result {
// ... do something ...
// now we can call the function recursively
return myFunc(arg)
}
在您的情况下,常规func声明不起作用,因此您需要某种“前向声明”来使名称可用,这需要少量重复:
// forward declare the function
var myFunc func(arg) result
myFunc = func(arg) result {
// ... do something ...
// now we can call the function recursively
return myFunc(arg)
}
要在全球范围内做同样的事情,请参阅Burak 的回答。
TA贡献1765条经验 获得超5个赞
问题是初始化循环,而不是递归。您指的是该变量定义中的变量。你可以做:
var lookup func() func(payload interface{}) map[string]interface{}
func init() {
lookup=func() func(payload interface{}) map[string]interface{} {...}
}
TA贡献1864条经验 获得超6个赞
我按照其他人的建议做了各种排列并遇到了同样的问题。最终,这就是我的工作
type AutoMapper func(field reflect.StructField, thing reflect.Value) map[string]interface{}
func checkForHcl(mapper AutoMapper) AutoMapper {
return func(field reflect.StructField, thing reflect.Value) map[string]interface{} {
if field.Tag.Get("hcl") != "" {
return mapper(field, thing)
}
return map[string]interface{}{}
}
}
func findInspector(kind reflect.Kind) AutoMapper {
switch kind {
case reflect.Struct:
return checkForHcl(func(f reflect.StructField, t reflect.Value) map[string]interface{} {
return lookup(t.Interface())
})
case reflect.Ptr:
return checkForHcl(func(field reflect.StructField, thing reflect.Value) map[string]interface{} {
deref := reflect.Indirect(thing)
if deref.CanAddr() {
if deref.Kind() == reflect.Struct {
return lookup(deref.Interface())
}
return map[string]interface{}{
field.Tag.Get("hcl"): deref.Interface(),
}
}
return map[string]interface{}{}
})
case reflect.Slice:
return checkForHcl(func(field reflect.StructField, thing reflect.Value) map[string]interface{} {
return map[string]interface{}{
field.Tag.Get("hcl"): castToInterfaceArr(thing.Interface().([]string)),
}
})
}
return checkForHcl(func(field reflect.StructField, thing reflect.Value) map[string]interface{} {
return map[string]interface{}{
field.Tag.Get("hcl"): thing.Interface(),
}
})
}
func lookup(payload interface{}) map[string]interface{} {
values := map[string]interface{}{}
var t = reflect.TypeOf(payload)
var v = reflect.ValueOf(payload)
if t.Kind() == reflect.Ptr {
t = t.Elem()
v = v.Elem()
}
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
thing := v.Field(i)
typeInspector := findInspector(thing.Kind())
for key, value := range typeInspector(field, thing) {
values[key] = value
}
}
return values
}
- 3 回答
- 0 关注
- 100 浏览
添加回答
举报