我如何在golang中进行这种递归

我有下面的代码,我正在尝试进行递归。但是,go 编译器抱怨循环引用。当然我有一个循环引用;这是一个递归。


我尝试将递归移入主函数并移出。同样的问题。我怎样才能实现这种递归?错误行是:return lookup(deref.Interface()) // recursion error 'cyclic definition'


christianb@christianb-mac terraform-provider% go build

# github.com/terraform-provider/pkg/foo/repositories.go:773:5: initialization loop:

        /Users/christianb/dev/terraform-provider/pkg/foo/repositories.go:773:5: lookup refers to

        /Users/christianb/dev/terraform-provider/pkg/foo/repositories.go:774:18: glob..func6.1 refers to

        /Users/christianb/dev/terraform-provider/pkg/foo/artifactory/repositories.go:773:5: lookup


type AutoMapper func(field reflect.StructField, thing reflect.Value) map[string]interface{}


var lookup = func() func(payload interface{}) map[string]interface{} {

    var handlePtr = 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()) // recursion error 'cyclic definition'

            }

            return map[string]interface{}{

                field.Tag.Get("hcl"): deref.Interface(),

            }

        }

        return map[string]interface{}{}

    }

    var checkForHcl = func(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{}{}

        }

    }

    lk := map[reflect.Kind]AutoMapper{}


    find := func(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()

        }


芜湖不芜
浏览 101回答 3
3回答

茅侃侃

您的函数不能通过名称引用自身,因为它是一个匿名函数。它只有在分配给变量后才会被命名lookup。从词法上讲,这仅在分配的值被完全解析后才会发生。这与普通func声明不同,后者的名称立即可用(这使得递归更加简洁):func myFunc(arg) result {    // ... do something ...    // now we can call the function recursively    return myFunc(arg)}在您的情况下,常规func声明不起作用,因此您需要某种“前向声明”来使名称可用,这需要少量重复:// forward declare the functionvar myFunc func(arg) resultmyFunc = func(arg) result {    // ... do something ...    // now we can call the function recursively    return myFunc(arg)}要在全球范围内做同样的事情,请参阅Burak 的回答。

POPMUISE

问题是初始化循环,而不是递归。您指的是该变量定义中的变量。你可以做:var lookup func() func(payload interface{}) map[string]interface{}func init() {   lookup=func() func(payload interface{}) map[string]interface{} {...}}

慕尼黑的夜晚无繁华

我按照其他人的建议做了各种排列并遇到了同样的问题。最终,这就是我的工作type AutoMapper func(field reflect.StructField, thing reflect.Value) map[string]interface{}func checkForHcl(mapper AutoMapper) AutoMapper {&nbsp; &nbsp; return func(field reflect.StructField, thing reflect.Value) map[string]interface{} {&nbsp; &nbsp; &nbsp; &nbsp; if field.Tag.Get("hcl") != "" {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return mapper(field, thing)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return map[string]interface{}{}&nbsp; &nbsp; }}func findInspector(kind reflect.Kind) AutoMapper {&nbsp; &nbsp; switch kind {&nbsp; &nbsp; case reflect.Struct:&nbsp; &nbsp; &nbsp; &nbsp; return checkForHcl(func(f reflect.StructField, t reflect.Value) map[string]interface{} {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return lookup(t.Interface())&nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; case reflect.Ptr:&nbsp; &nbsp; &nbsp; &nbsp; return checkForHcl(func(field reflect.StructField, thing reflect.Value) map[string]interface{} {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; deref := reflect.Indirect(thing)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if deref.CanAddr() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if deref.Kind() == reflect.Struct {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return lookup(deref.Interface())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return map[string]interface{}{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; field.Tag.Get("hcl"): deref.Interface(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return map[string]interface{}{}&nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; case reflect.Slice:&nbsp; &nbsp; &nbsp; &nbsp; return checkForHcl(func(field reflect.StructField, thing reflect.Value) map[string]interface{} {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return map[string]interface{}{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; field.Tag.Get("hcl"): castToInterfaceArr(thing.Interface().([]string)),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; }&nbsp; &nbsp; return checkForHcl(func(field reflect.StructField, thing reflect.Value) map[string]interface{} {&nbsp; &nbsp; &nbsp; &nbsp; return map[string]interface{}{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; field.Tag.Get("hcl"): thing.Interface(),&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; })}func lookup(payload interface{}) map[string]interface{} {&nbsp; &nbsp; values := map[string]interface{}{}&nbsp; &nbsp; var t = reflect.TypeOf(payload)&nbsp; &nbsp; var v = reflect.ValueOf(payload)&nbsp; &nbsp; if t.Kind() == reflect.Ptr {&nbsp; &nbsp; &nbsp; &nbsp; t = t.Elem()&nbsp; &nbsp; &nbsp; &nbsp; v = v.Elem()&nbsp; &nbsp; }&nbsp; &nbsp; for i := 0; i < t.NumField(); i++ {&nbsp; &nbsp; &nbsp; &nbsp; field := t.Field(i)&nbsp; &nbsp; &nbsp; &nbsp; thing := v.Field(i)&nbsp; &nbsp; &nbsp; &nbsp; typeInspector := findInspector(thing.Kind())&nbsp; &nbsp; &nbsp; &nbsp; for key, value := range typeInspector(field, thing) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; values[key] = value&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return values}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go