英文:
Go Plugin variable initialization
问题
这是关于Go插件初始化的一般问题。
我想将Go程序中的某个包制作成一个Go插件。
该包(假设为mypackage
)有一个变量,它通过可执行文件中某个包的函数调用进行初始化(例如,一个类型为interface Logger
的变量,通过logger.CreateLogger
函数进行初始化)。
为了将mypackage
制作成插件,我需要创建一个main
包,将mypackage
嵌入到main
中,并在main
包中导出一个名为Init
的API,该API接受一个函数,该函数可以获取一个日志记录器。
我想这样做是为了减少插件的依赖性。mypackage
插件应该依赖于interface Logger
而不是Logger的实现。
现在的问题是初始化,在可执行文件的情况下,初始化可以如下进行:
package mypackage
var dlog = logger.CreateLogger("mypackage")
并且日志记录器可以在mypackage
的任何func init()
函数中使用。
转换为插件后,无法像这样进行初始化。它必须在调用main.Init
之后的某个时间点进行初始化。
func init
在插件被打开时被调用,因此不能用于初始化变量。
唯一的解决方案似乎是为每个包创建一个函数,并从main
包中的一个导出函数中调用它。
package mypackage
var dlog Logger
func Init(f createLoggerType){
dlog = f()
yetanotherpackage.Init(f)
}
package main
func Init(f createLoggerType) {
mypackage.Init(f)
anotherpackage.Init(f)
}
有没有更好的初始化方法?我尝试过检查github.com/facebookgo/inject
,但无法弄清楚在插件的情况下如何使用它。
英文:
This is a general question about Go Plugin initialization.
I want to make a certain package in a Go program to a Go Plugin.
The package (say mypackage
) has a variable which is initialized with a function call from a certain package in the executable. (E.g. a variable of type interface Logger
which is to be initialized by a logger.CreateLogger
function.)
In order to make mypackage
a plugin, I need to create a main
package, embed mypackage
inside main
, and export an api Init
in package main
which accepts a function which can get me a logger.
I want to do this so as to reduce the dependencies of my plugin. The mypackage
plugin should depend on the interface Logger
rather than Logger's implementation.
Now the problem is the initialization, in the case of executable, the initialization could have happened as below:
package mypackage
var dlog = logger.CreateLogger("mypackage")
And the logger can be used in any func init()
function of mypackage
.
After converting to a plugin, it can't be initialized like this. It has to be initialized at a later point after the main.Init
is invoked.
The func init
is invoked when the plugin is Opened, so it cannot be used to initialize variables.
Only solution seems to be a creating a function per package, and invoke it from an exported function in main
package.
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)
}
Is there a better way to initialize? I tried checking github.com/facebookgo/inject
but couldn't figure out how it can be used in case of plugins.
答案1
得分: 1
你的解决方案没有问题,但如果你想在变量声明和包的init()
函数中使用它,可以按照以下方式进行操作。我认为这种方式更容易使用插件,但这需要在主应用程序和插件之间创建一个共享的公共包。
一种选择是创建一个名为"store"的包,该包可以存储工厂函数或预先创建的日志记录器。
假设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
// 现在继续加载/打开mypackage插件
}
然后,mypackage
插件可能如下所示:
package mypackage
import "store"
var dlog = store.LoggerFactory("mypackage")
英文:
There is nothing wrong with your solution, but if you want to be able to use it in variable declarations and package init()
functions, this is how you can do it. I also think it's easier to use the plugin this way, but this requires a common, shared package between your main app and the plugin.
One option would be to create a "store" package, which could store factory functions or pre-created loggers.
Let's say the Logger
interface definition is in mylogger
:
package mylogger
type Logger interface { Log(string) }
The store
for example:
package store
import "mylogger"
var LoggerFactory func(string) mylogger.Logger
And in your main app initialize it before you load / open the mypackage
plugin:
package main
import "store"
func main() {
store.LoggerFactory = logger.CreateLogger
// Now proceed to load / open mypackage plugin
}
Then the mypackage
plugin may look like this:
package mypackage
import "store"
var dlog = store.LoggerFactory("mypackage")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论