在寫C++程序時,時常須要將一個class寫成DLL(動態連接庫),供客戶端程序調用。這樣的DLL能夠導出整個class,也能夠導出這個class的某個方法。golang
經過DLL調用和把代碼寫在程序裏調用的區別:看這個函數是否提供給別的程序調用;算法
別的程序確定無法調用這個程序的某個函數,總不能把代碼拷給他把,且不說可不能夠拷,就算能夠也麻煩阿,直接寫成DLL讓他本身調用去;安全
插件就相似dll;模塊化
經過使用插件在運行時擴展程序的功能, 而無需從新編譯程序;函數
啓動啓程以後不用中止就能添加新的功能(函數);測試
優勢:ui
缺點:編碼
Go插件是使用-buildmode = plugin
標記編譯的一個包, 用於生成一個共享對象(.so)庫文件。spa
Go包中的導出的函數和變量被公開爲ELF符號,可使用plugin
包在運行時查找並綁定ELF符號。這樣就能夠查詢並調用插件裏的函數;插件
用plugin.Open()打開插件文件
用plguin.Lookup(「Export-Variable-Name」)查找導出的符號」Car」或者」Phone」(就是函數名)
請注意,符號名稱與插件模塊中定義的變量名稱相匹配
類型斷言,而後就能夠進行調用了
go build -buildmode=plugin file.go,編譯生成插件
==go中的插件不是進程隔離的,是單進程的;==
golang的插件很不完善,只能加載不能卸載。如何須要卸載須要本身實現一套重載機制。
Go plugin判斷兩個插件是否相同是經過比較pluginpath實現的,若是沒有指定pluginpath,則由內部的算法生成, 生成的格式爲plugin/unnamed-「 + root.Package.Internal.BuildID 。
在開始編碼以前,要先解決幾個問題:
1、同一個so文件只會被打開一次
2、每一個so有一個pluginpath用來標識是否重複,若是兩個so文件不同,但pluginpath同樣仍是會報錯。會被識別成是同一個文件,同時加載這兩個插件時,會報錯;
3、不一樣so文件定義的結構體不能使用類型斷言進行轉換
對於上面的問題,有以下解決方案:
編譯的時候新增--ldflags="-pluginpath=xxx"參數,本身指定pluginpath參數,避免重複。
複製代碼
加載.so文件的時候,就會爲全局變量申請內存空間,同時執行init()初始化函數;
同一進程空間內的線程:
堆:是你們共有的空間
棧:是個線程獨有的
同一進程空間,函數能夠直接相互調用;
複製代碼
思考:我在插件中調用項目的其餘部分,如models,編譯插件的時候不會報錯嗎?我插件都還沒加載?
首先插件又叫動態庫,和靜態庫沒什麼區別。靜態庫就是程序編譯完了以後,再來修改靜態庫就程序不起做用,要從新編譯才行。
而動態庫就不一樣了,在程序編譯運行以後,動態庫能夠照樣更改,改完以後程序從新加載一遍就完事了;
至於插件中調用了models,毛問題都沒有,插件編譯的時候都沒調用到models,並且插件只是編譯而已,就算調用有問題,那也是等插件被加載以後的事情了;