doufei4923 2012-09-01 20:37
浏览 12
已采纳

Go中的嵌入式程序包?

How would I go about having a package register some object (for instance a function) to a registry at load time such that adding a new package to the program will automatically add new functionality to the program without having to modify code in other packages?

Here's a code sample which should illustrate what I'm trying to do.

src/say/say.go:

package main

import (
    "os"
    "reg"
)

func main() {
    if len(os.Args) != 2 {
        os.Stderr.WriteString("usage:
    say <what_to_say>
")
        os.Exit(1)
    }

    cmd, ok := reg.GetFunc(os.Args[1])
    if ok {
        os.Stdout.WriteString(cmd())
        os.Stdout.Write([]byte{'
'})
    } else {
        os.Stderr.WriteString("I can't say that!
")
        os.Exit(1)
    }
}

src/reg/reg.go:

package reg

var registry = make(map[string]func() string)

func Register(name string, f func() string) {
    registry[name] = f
}

func GetFunc(name string) (func() string, bool) {
    f, ok := registry[name]
    return f, ok
}

src/hi/hi.go:

package hi

import (
    "reg"
}

func init() {
    reg.Register("hi", func() string {
        return "Hello there!"
    })
}

When coding this up, I naively supposed that perhaps the package "hi" would be found by the go compiler and compiled into the binary. Then, at load time, the init() function would run. If that was how things worked, I'd have been able to drop in something like the following to add a new "say no" command:

src/no/no.go:

package no

import (
    "reg"
)

func init() {
    reg.Register("no", func() string {
        return "Not a chance, bub."
    })
}

But, it doesn't seem to work that way.

I may just be thinking about the problem too much through a Pythonic lens, but is there some way to accomplish something somewhat like what I'm shooting for? If not, I'll change my tack and I will have learned something new about the Go way of doing things.

Thanks in advance!

  • 写回答

2条回答 默认 最新

  • 普通网友 2012-09-03 06:40
    关注

    Since you must use import in order for the compiler add a package, my suggestion would be to do the following:

    Instead of using multiple drop-in packages, you could have only one single package with multiple drop-in files. Each command file is placed in the same package folder (cmds). This is possible since you are allowed to have multiple init in a package, and you would not have to make any edits to say.go, no matter how many new drop-in files you add.

    package main
    
    import (
        "os"
        "reg"
        _ "cmds"
    )
    ....
    

    And previous package no

    // Command no
    package cmds
    
    import (
        "reg"
    )
    
    func init() {
        reg.Register("no", func() string {
            return "Not a chance, bub."
        })
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料