這是關於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