donglin9068 2013-10-28 10:54
浏览 122
已采纳

在Go中使用递归引用

I want to contain all my commands in a map and map from the command to a function doing the job (just a standard dispatch table). I started with the following code:

package main

import "fmt"

func hello() {
    fmt.Print("Hello World!")
}

func list() {
    for key, _ := range whatever {
        fmt.Print(key)
    }
}

var whatever = map[string](func()) {
    "hello": hello,
    "list": list,
}

However, it fails to compile because there is a recursive reference between the function and the structure. Trying to forward-declare the function fails with an error about re-definition when it is defined, and the map is at top-level. How do you define structures like this and initialize them on top level without having to use an init() function.

I see no good explanation in the language definition.

  • The forward-reference that exists is for "external" functions and it does not compile when I try to forward-declare the function.
  • I find no way to forward-declare the variable either.

Update: I'm looking for a solution that do not require you to populate the variable explicitly when you start the program nor in an init() function. Not sure if that is possible at all, but it works in all comparable languages I know of.

Update 2: FigmentEngine suggested an approach that I gave as answer below. It can handle recursive types and also allow static initialization of the map of all commands.

  • 写回答

3条回答 默认 最新

  • douqi1625 2013-10-30 10:17
    关注

    Based on the suggestion by FigmentEngine above, it is actually possible to create a statically initialized array of commands. You have, however, to pre-declare a type that you pass to the functions. I give the re-written example below, since it is likely to be useful to others.

    Let's call the new type Context. It can contain a circular reference as below.

    type Context struct {
        commands map[string]func(Context)
    }
    

    Once that is done, it is possible to declare the array on top level like this:

    var context = Context {
        commands: map[string]func(Context) {
            "hello": hello,
            "list": list,
        },
    }
    

    Note that it is perfectly OK to refer to functions defined later in the file, so we can now introduce the functions:

    func hello(ctx Context) {
        fmt.Print("Hello World!")
    }
    
    func list(ctx Context) {
        for key, _ := range ctx.commands {
            fmt.Print(key)
        }
    }
    

    With that done, we can create a main function that will call each of the functions in the declared context:

    func main() {
        for key, fn := range context.commands {
            fmt.Printf("Calling %q
    ", key)
            fn(context)
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 找人不需要人工智能回答的gamit解算后做形变分析
  • ¥20 RL+GNN解决人员排班问题时梯度消失
  • ¥15 统计大规模图中的完全子图问题
  • ¥15 使用LM2596制作降压电路,一个能运行,一个不能
  • ¥60 要数控稳压电源测试数据
  • ¥15 能帮我写下这个编程吗
  • ¥15 ikuai客户端l2tp协议链接报终止15信号和无法将p.p.p6转换为我的l2tp线路
  • ¥15 phython读取excel表格报错 ^7个 SyntaxError: invalid syntax 语句报错
  • ¥20 @microsoft/fetch-event-source 流式响应问题
  • ¥15 ogg dd trandata 报错