这是关于Go插件初始化的一般问题。Go插件变量初始化
我想在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")
而且记录器可以在任何mypackage
功能func init()
使用。
转换为插件后,无法像这样初始化。必须在调用main.Init
后稍后进行初始化。
当插件是Opened时调用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
,但无法弄清楚如何在插件的情况下使用它。
谢谢您的回答。 1)记录器是由框架创建的,所以我无法从插件中创建记录器。记录器框架位于打开插件的可执行文件中,2)我的观点是让插件本身不包含记录器框架。而是取决于在加载插件时将被初始化的记录器接口。插件只需要告诉它需要哪种类型的记录器。之后插件在界面上工作。 3)'init'不能被使用,因为在任何'plugin.Lookup'可以执行之前调用'init' – weima
@weima请参阅编辑答案。现在插件不会创建记录器,它不会引用记录器实现。 – icza
换句话说,你的解决方案是:不是将'createLoggerType'作为参数传递给它的'InitPlugin'函数,而是在可执行文件中创建一个新的包,它在导出的变量中保存相同的函数,这个'package商店“有一个最小的依赖关系。这正是我想要避免的,插件除了提供给插件的接口和实现之外,还导入其他任何东西,而不是插件来决定实现。以及如果我想在运行时决定记录器的工厂,取决于插件类型。 – weima