Go 的构建模式
Go 的八种 Build Mode
exe
(静态编译)exe
(动态链接libc
)exe
(动态链接libc
和非 Go 代码)pie
地址无关可执行文件(安全特性)c-archive
C 的静态链接库c-shared
C 的动态链接库shared
Go 的动态链接库plugin
Go 的插件
plugin
Go 的插件
插件形式和 c-shared
、shared
相似,都是构建一个动态链接库,和 shared
一样,这是构建一个 Go 专用的动态链接库,而和 shared
不同的是,动态链接库并非在程序启动时加载,而是由程序内决定何时加载和释放。
我们创建一个 plugin,myplugin.go
:
package main import "fmt" func Hello() { fmt.Println("Hello, World!") }
可以看到,这和最初那个静态链接库的性质相似。不过不同的是,这里既没有 import "C"
,也没有 //export Hello
,而且也没有 func main()
。
因为这里不需要,我们是 Go 调用 Go 的代码,因此很多东西都省了。
调用代码这么写:
package main import "plugin" func main() { // 加载 myplugin 库 p, err := plugin.Open("myplugin.so") if err != nil { log.Fatal(err) } // 取得 Hello 函数 fn, err := p.Lookup("Hello") if err != nil { log.Fatal(err) } // 调用函数 fn.(func())() }
可以看到,这个逻辑上,和 hello-dyn.c
很相似。plugin.Open()
有点儿像 dlopen()
;而 p.Lookup()
有点儿像 dlsym()
。
实际上也是如此,底层实现的时候就是调用的这两个函数。
注意这里的 fn.(func())()
,p.Lookup()
返回的是一个 interface{}
,因此这里需要转型为具体函数类型。
用下面的命令构建:
go build -buildmode=plugin myplugin.go go build runplugin.go
前者会生成一个 myplugin.so
,后者会生成调用者 runplugin
。
-rw-r--r-- 1 root root 3.8M Oct 3 13:58 myplugin.so -rwxr-xr-x 1 root root 3.5M Oct 3 13:58 runplugin
转载文章:https://blog.lab99.org/post/golang-2017-10-01-video-go-build-mode.html