Go插件变量初始化

huangapple go评论75阅读模式
英文:

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")

huangapple
  • 本文由 发表于 2017年4月3日 17:47:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/43181410.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定