2017-04-03 52 views
3

這是關於Go插件初始化的一般問題。Go插件變量初始化

我想在GO程序中將某個程序包製作爲Go插件。

該軟件包(比如說mypackage)有一個變量,該變量用來自可執行文件中某個包的函數調用進行初始化。 (例如interface Logger類型的變量,其是由一個logger.CreateLogger函數被初始化。)

爲了使mypackage一個插件,我需要創建一個main包,嵌入mypackage內部main,並在包輸出的API Initmain它接受一個功能,可以讓我一個記錄器。

我想這樣做,以減少我的插件的依賴關係。 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

您的解決方案沒有問題,但是如果您希望能夠在變量聲明和包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") 
+0

謝謝您的回答。 1)記錄器是由框架創建的,所以我無法從插件中創建記錄器。記錄器框架位於打開插件的可執行文件中,2)我的觀點是讓插件本身不包含記錄器框架。而是取決於在加載插件時將被初始化的記錄器接口。插件只需要告訴它需要哪種類型的記錄器。之後插件在界面上工作。 3)'init'不能被使用,因爲在任何'plugin.Lookup'可以執行之前調用'init' – weima

+0

@weima請參閱編輯答案。現在插件不會創建記錄器,它不會引用記錄器實現。 – icza

+0

換句話說,你的解決方案是:不是將'createLoggerType'作爲參數傳遞給它的'InitPlugin'函數,而是在可執行文件中創建一個新的包,它在導出的變量中保存相同的函數,這個'package商店「有一個最小的依賴關係。這正是我想要避免的,插件除了提供給插件的接口和實現之外,還導入其他任何東西,而不是插件來決定實現。以及如果我想在運行時決定記錄器的工廠,取決於插件類型。 – weima