这是关于Go Plugin初始化的一般问题。
我想在Go程序中创建一个Go包插件。
包(比如mypackage
)有一个变量,它使用来自可执行文件中某个包的函数调用进行初始化。 (例如,interface Logger
类型的变量,由logger.CreateLogger
函数初始化。)
为了使mypackage
成为插件,我需要创建一个main
包,在mypackage
中嵌入main
,然后导出一个api Init
包main
,它接受一个可以让我记录器的功能。
我想这样做,以减少我的插件的依赖性。 mypackage
插件应取决于interface Logger
而不是Logger的实现。
现在问题是初始化,在可执行的情况下,初始化可能发生如下:
package mypackage
var dlog = logger.CreateLogger("mypackage")
记录器可用于func init()
的任何mypackage
函数。
转换为插件后,无法像这样进行初始化。它必须在调用main.Init
后的稍后时间进行初始化。
插件打开时调用func init
,因此不能用于初始化变量。
只有解决方案似乎是为每个包创建一个函数,并从main
包中的导出函数调用它。
package mypackage
var dlog Logger
func Init(f createLoggerType){
dlog = f()
yetanotherpackage.Init(f)
}
package main
func Init(f createLoogerType) {
mypackage.Init(f)
anotherpackage.Init(f)
}
有没有更好的初始化方法?我尝试检查github.com/facebookgo/inject
,但无法弄清楚如何在插件中使用它。
答案 0 :(得分:1)
您的解决方案没有任何问题,但如果您希望能够在变量声明和包init()
函数中使用它,那么您就可以这样做。我也认为以这种方式使用插件更容易,但这需要在主应用程序和插件之间使用通用的共享包。
一种选择是创建一个"商店"包,可以存储工厂功能或预先创建的记录器。
我们说Logger
接口定义在mylogger
中:
package mylogger
type Logger interface { Log(string) }
store
例如:
package store
import "mylogger"
var LoggerFactory func(string) mylogger.Logger
在您的主应用中初始化,然后加载/打开mypackage
插件:
package main
import "store"
func main() {
store.LoggerFactory = logger.CreateLogger
// Now proceed to load / open mypackage plugin
}
然后mypackage
插件可能如下所示:
package mypackage
import "store"
var dlog = store.LoggerFactory("mypackage")