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:\n say <what_to_say>\n")
os.Exit(1)
}
cmd, ok := reg.GetFunc(os.Args[1])
if ok {
os.Stdout.WriteString(cmd())
os.Stdout.Write([]byte{'\n'})
} else {
os.Stderr.WriteString("I can't say that!\n")
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!