利用Go Plugin實現插件化編程的簡單方法
前言
說到插件這個東西,很多人都不陌生,一般來說,插件化有幾個好處,一個是增加程序擴展性,豐富功能。另外,還可以實現熱更新,有些大型應用,動輒幾個GB的安裝程序,如果一個小小的更新就需要重新下載整個程序,這時候我們就可以把經常更新的模塊插件化,這樣更新的時候隻需要下載一個小更新文件。比如說平時咱們Chrome瀏覽器都會裝一些插件,可以擴展瀏覽器實現更多的功能,還能靈活的安裝卸載。
Golang在1.8版本之後提供瞭一個 Plugin 的機制,可以動態的加載so文件,實現插件化,雖然並不是非常成熟,但是在特定的情況下還是非常好用。
Currently plugins are only supported on Linux, FreeBSD, and macOS.
1.快速開始
插件代碼和普通代碼沒什麼區別,隻是在編譯的時候不一樣,但是要求是必須隻有一個main包
package main var Name = "Plugin Name" func GetName() string { return Name }
使用go build -buildmode=plugin編譯,會得到一個so文件,怎麼使用這個文件呢?
很簡單,分三步:
1.先打開so文件,如果一個插件已經被打開瞭,那麼會返回已存在的plugin
2.使用Lookup查找需要調用的變量或者函數,名字必須大寫開頭
3.斷言後調用
func main() { //打開加載插件,參數是插件的存儲位置,可以是相對路徑 open, err := plugin.Open("/home/jwang/Documents/plg.so") if err != nil { panic(err) } //查找標識符 lookup, err := open.Lookup("GetName") if err != nil { panic(err) } res := lookup.(func() string)() fmt.Printf("%v\n", res) name, err := open.Lookup("Name") if err != nil { panic(err) } fmt.Printf("%v\n", *name.(*string)) }
從上面的代碼可以看到,插件的使用方式非常樸實無華,簡單易懂。
一般來說,為瞭實現插件化,可以事先定義好一些接口,然後由插件去實現這些接口,這樣才能保證一致性,但是接口的定義不能寫在插件包或者調用包裡面。這時候就需要定義一個專門的公共包,把接口的定義寫在裡面,這樣插件包和調用包都可以引用。
2.註意事項
之所以說這個插件方案不成熟,主要是由於主程序和插件程序之間存在很強的依賴性,比如:
1.編譯的GO版本必須完全一致
2.雙方依賴的公共第三方庫版本必須完全一致
3.GOPATH也得保持一致,這一點可以在編譯時候使用trimpath參數解決
4.插件加載之後無法卸載
這些問題短時間內好像官方也沒有解決的意思,或者說無法解決。總之,Go plugin目前的應用很少,畢竟作為網絡編程語言,在容器化大行其道的環境下,更新程序是一件很輕松的事情,除非有特殊需要。
總結
到此這篇關於利用Go Plugin實現插件化編程的文章就介紹到這瞭,更多相關Go Plugin插件化編程內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Go Plugins插件的實現方式
- go設置多個GOPATH的方式
- Golang中panic的異常處理
- go語言中GOPATH GOROOT的作用和設置方式
- Golang 使用Map實現去重與set的功能操作