Golang中的编译参数
go build
go build
环境变量
环境变量需要在go命令前面设置,如果多个变量的话,中间需要用“空格”分隔。下面我们介绍一个非常常见到的一些环境变量
$ CGO_ENABLED=1 GOARCH=amd64 GOOS=linux go build -o myserver main.go
除了这里给出的这几个变量外,还有一些其它变量,如 GODEBUG、GOFLAGS、GOPROXY 等,所有支持环境变量都可以在 https://github.com/golang/go/blob/a88575d662a7e8e4fbb31bf139bcffc063e2a734/src/cmd/go/internal/help/helpdoc.go#L485 里找到,有兴趣的话可以看看他们的作用。
CGO_ENABLEDCGO_ENABLEDgo env
如果你的程序里调用了cgo 命令,此参数必须设置为1,否则将编译时出错。这里直接用文档 https://go.dev/blog/cgo 中的一个例子验证。
package main // #include <stdio.h> // #include <stdlib.h> // // static void myprint(char* s) { // printf("%sn", s); // } import "C" import "unsafe" func main() { cs := C.CString("Hello from stdio") C.myprint(cs) C.free(unsafe.Pointer(cs)) }
然后我们执行一下 启用 CGO_ENABLED=1 的情况
root@ubuntu:/home/sxf/gotest# CGO_ENABLED=1 go run main.go root@ubuntu:/home/sxf/gotest# ./main Hello from stdio
可以看到输出正常,这里也可以省略不写变量,因为默认情况为启用CGO状态
启用 CGO_ENABLED=0 的情况
root@ubuntu:/home/sxf/gotest# CGO_ENABLED=0 go build main.go go: no Go source files
可以看到编译失败,验证了我们上面说的情况。
这里提示找不到go源文件,不清楚底层是如何判断这一情况的。
CGO_ENABLED
root@ubuntu:/home/sxf/gotest# CGO_ENABLED=1 go build -o cgo_main main.go root@ubuntu:/home/sxf/gotest# CGO_ENABLED=0 go build -o no_cgo_main main.go root@ubuntu:/home/sxf/gotest# ls -al total 3804 drwxrwxr-x 2 sxf sxf 4096 Nov 25 10:22 . drwxr-x--- 47 sxf sxf 4096 Nov 19 12:48 .. -rwxr-xr-x 1 root root 1937311 Nov 25 10:22 cgo_main -rw-rw-r-- 1 sxf sxf 119 Oct 29 09:07 go.mod -rw-rw-r-- 1 sxf sxf 241 Oct 29 09:07 go.sum -rw-rw-r-- 1 sxf sxf 72 Nov 25 10:21 main.go -rwxr-xr-x 1 root root 1937311 Nov 25 10:22 no_cgo_main
可以看到两种情况都可能编译成功,且两者生成的二进制文件是完全一样的。由此总结出可以看出如果程序里未调用 cgo 的话,此变量值并没有影响的。
那么问题来了,为什么这么多项目里编译的时候都明确指定了此环境变量的值呢,主要是编译器在编译时会根据不同的情况使用不同的编译方法。 当CGO_ENABLED=1,进行编译时会将文件中引用libc的库(比如常用的net包),以动态链接的方式生成目标文件。 当CGO_ENABLED=0,进行编译时则会把在目标文件中未定义的符号(外部函数)一起链接到可执行文件中。
不论哪种方式,都可以使用静态连接编译
参考