1. 程式人生 > >Go生成go動態庫或靜態庫

Go生成go動態庫或靜態庫

Go生成go動態庫或靜態庫

預備知識

  1. plugin模式
  2. 外掛執行方式
  3. go plugin包使用

相關知識

go build 可以指定buildmode。分為了多種模式。具體模式如下。

模式 說明
當前go版本 1.10.3
archive 編譯成二進位制檔案。一般是靜態庫檔案。 xx.a
c-archive 編譯成C歸檔檔案。C可呼叫的靜態庫。xx.a。注意要編譯成此類檔案需要import C 並且要外部呼叫的函式要使用 “//export 函式名” 的方式在函式上方註釋。否則函式預設不會被匯出。
c-shared 編譯成C共享庫。同樣需要 import “C” 和在函式上方註釋 // export xxx
default 對於有main包的直接編譯成可執行檔案。沒有main包的,編譯成.a檔案
exe 編譯成window可執行程式
plugin 將main包和依賴的包一起編譯成go plugin。非main包忽略。【類似C的共享庫或靜態庫。外掛式開發使用】

例項

結構:
    -softplugin         //根目錄
        -soft           //軟體目錄
        -plugins         //外掛目錄
        -itf            //介面目錄

無自定義資料

// plugins/hello.go
package main
import "fmt"
func Hello(){
    fmt.Println("hello")
}
// go build -buildmode=plugin -o hello.so hello.go


// soft/basetype.go
package main
import (
    "os"
    "path"
    "plugin"
    "fmt"
)

func main(){
    //載入外掛
    pluginDir := "../plugins"
    //掃描資料夾下所有so檔案
    f,
err := os.OpenFile(pluginDir, os.O_RDONLY, 0666) if err != nil { panic(err) } fi, err := f.Readdir(-1) if err != nil { panic(err) } plugins := make([]os.FileInfo, 0) for _, ff := range fi { if ff.IsDir() || path.Ext(ff.Name()) != ".so" { continue } plugins = append(plugins, ff) pdll, err := plugin.Open(pluginDir + "/" + ff.Name()) if err != nil { fmt.Println(err) continue } plg, err := pdll.Lookup("Hello") if err != nil { panic(err) } plg.(func())() } } // go run basetype.go

定義外掛介面 interface。

//------------------------------------------------------
// itf/itf1.go
package itf
type Printor interface{
    Print(v interface{})
}

//------------------------------------------------------
// plugins/p1.go
package main
import (
    "fmt"
    "softplugin/itf"
)
type ScreenPrintor struct{}
func (ScreenPrintor)Print(v interface{}){
    fmt.Println("p1p1 ",v)
}
func Install() Printor{
    return &ScreenPrintor{}
}

//-----------------------------------------------------
// soft/s1.go
package main
import (
    "softplugin/itf"
    "os"
    "path"
    "plugin"
    "fmt"
)
var(
    printors = make([]itf.Printor, 0)
)

func main(){
    //載入外掛
    pluginDir := "../plugins"
    //掃描資料夾下所有so檔案
    f, err := os.OpenFile(pluginDir, os.O_RDONLY, 0666)
    if err != nil {
        panic(err)
    }
    fi, err := f.Readdir(-1)
    if err != nil {
        panic(err)
    }
    plugins := make([]os.FileInfo, 0)
    for _, ff := range fi {
        if ff.IsDir() || path.Ext(ff.Name()) != ".so" {
            continue
        }
        plugins = append(plugins, ff)
        pdll, err := plugin.Open(pluginDir + "/" + ff.Name())
        if err != nil {
            fmt.Println(err)
            continue
        }
        plg, err := pdll.Lookup("Hello")
        if err != nil {
            panic(err)
        }
       printors = append(printors, (plg.(func() itf.Printor))())
    }
    for _, p := range printors {
        p.Print("pppp")
    }
    
}