[Go] go build 的 -buildmode 参数

877 阅读2分钟

一、理论部分

官方文档表示该参数可以指定build的目标文件类型:

The 'go build' and 'go install' commands take a -buildmode argument which indicates which kind of object file is to be built.

MIT6.824的课程中用到了plugin模式,官方文档这样描述:

-buildmode=plugin
Build the listed main packages, plus all packages that they import, into a Go plugin. Packages not named main are ignored.

main包编译为一个插件,即生成一个动态链接.so文件(Linux的so文件到底是干嘛的?)。 语法通常为:

go build -buildmode=plugin -o [目标文件名.so] 源文件名.go

如果你不指定目标.so的文件名,go build将自动设置为同名文件。

二、实践部分

下面从 源码shell命令 演示如何动态调用这个.so文件。

1.被调的插件

源码:

// wc.go
package main  
// ↑ 注意必须声明在 main 包下,否则将被 -buildmode=plugin 忽略(但源文件本身可放在任意目录下)  
import (
... 
)

// 实现所需的若干函数

func Map(filename string, contents string) []mr.KeyValue {  
    ...
}  

func Reduce(key string, values []string) string {  
    ...
}

shell命令:
然后使用-buildmode = plugin参数将源码文件及其依赖包编译为一个.so插件:

go build -race -buildmode=plugin ../mrapps/wc.go

这将在main/下生成与源文件wc.go同名的wc.so插件。

2.主调的代码

源码:

// mrsequential.go
package main

import (
	...
	"plugin"   // 导入 go 官方自带的 plugin 库
        ...
)

...
...

// 调用.so 插件相关代码   
func loadPluginSeq(filename string) (func(string, string) []mr.KeyValue, func(string, []string) string) {  
    p, err := plugin.Open(filename)  // 1.实参: .so文件所在的相对路径
    if err != nil {  
        log.Fatalf("cannot load plugin %v", filename)  
    }  
    xmapf, err := p.Lookup("Map")  //2.**按需**用 Lookup() 动态匹配函数名
    if err != nil {  
        log.Fatalf("cannot find Map in %v", filename)  
    }  
    mapf := xmapf.(func(string, string) []mr.KeyValue)  // 3.强制转换类型
    xreducef, err := p.Lookup("Reduce")  
    if err != nil {  
        log.Fatalf("cannot find Reduce in %v", filename)  
    }  
    reducef := xreducef.(func(string, []string) string)  
  
    return mapf, reducef  
}

shell命令:

go run -race mrsequential.go wc.so pg*.txt

其中,pg*.txt是待利用的 datasets

三、拓展阅读

其它可选的类型还有:

-buildmode = archive
-buildmode = c-archive
-buildmode = c-shared
-buildmode = default
-buildmode = shared
-buildmode = exe
-buildmode = pie
-buildmode = plugin