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 对于知识的学以致用的解释
  • ¥50 三种调度算法报错 有实例
  • ¥15 关于#python#的问题,请各位专家解答!
  • ¥200 询问:python实现大地主题正反算的程序设计,有偿
  • ¥15 smptlib使用465端口发送邮件失败
  • ¥200 总是报错,能帮助用python实现程序实现高斯正反算吗?有偿
  • ¥15 对于squad数据集的基于bert模型的微调
  • ¥15 为什么我运行这个网络会出现以下报错?CRNN神经网络
  • ¥20 steam下载游戏占用内存
  • ¥15 CST保存项目时失败