go build 编译优化

2021.01.30

Go 项目使用容器运行时报以下错误:

standard_init_linux.go:207: exec user process caused "no such file or directory"

网上查了一下原因:CGO has to be disabled for alpine.

Dockerfile 中使用的是 golang:1.14-alpine 镜像,Go build 编译参数如下:

GOOS=linux GOARCH=amd64 go build -ldflags "-w -s" -gcflags "-N -l" -mod=vendor -o ./bin/mytest .

显而易见添加 CGO_ENABLED=0 编译之后即可运行成功。CGO_ENABLED 默认是开启的,允许在 Go 代码中调用 C 代码。

go build 编译生产环境下使用的可执行文件一般会加一些优化参数,简单复习一下。

go build

Go语言的源码文件包含:

  • 命令源码文件:可执行程序的入口
  • 库源码文件:集中放置待被使用的程序实体(全局常量、全局变量、接口、结构体、函数等)
  • 测试源码文件:对前面两种源码文件中的程序实体的功能和性能进行测试

go build 命令用于编译我们指定的源码文件或代码包以及它们的依赖包。go build 对于库源码文件的代码包只会做检查性编译不会输出任何结果文件。有 main 函数的命令源码文件则编译输出二进制文件。

常用标记

以下常用标记对于 go installgo rungo test 同样有效

-a
    force rebuilding of packages that are already up-to-date.
    // 强行对所有涉及到的代码包进行重新构建,即使它们已经是最新
-n
    print the commands but do not run them.
  // 打印期间所用的命令但并不真正执行
-p n
    the number of builds that can be run in parallel.
    The default is the number of CPUs available.
  This edits config and provides no error if you surpass your core count
  // 执行任务的并行数量,默认 CPU 逻辑核数,即使超配也不会报错

-race
    enable data race detection.
    Supported only on linux/amd64, darwin/amd64 and windows/amd64.
  ...
  // 开启竞态条件检测
-v
    print the names of packages as they are compiled.
    ...
    // 打印被编译的代码包名字

-work
    print the name of the temporary work directory and
    do not delete it when exiting.
    ...
    // 打印编译时生成的临时工作目录路径,并在编译结束时保留它。默认情况编译结束会删除。

-x
    print the commands
  // 打印编译期间所用的的其他命令

编译选项

- asmflags  
  arguments to pass on each go tool asm invocation.
  // 控制 Go 语言编译器编译汇编语言文件时的行为
  
- buildmode 
  build mode to use
  // 指定编译模式,支持六种编译模式
  
- compiler  
  ame of compiler to use, as in runtime.Compiler (gccgo or gc).
  // 指定编译器,其值可为 gc 或 gccgo,gc 编译器即为 Go 语言自带编译器,gccgo 为 GCC 提供的编译器
  
- gccgoflags 'arg list'
  arguments to pass on each gccgo compiler/linker invocation.
  // 指定需要传递给 gccgo 编译器或链接器的标记的列表
  
- gcflags 'arg list'
  arguments to pass on each go tool compile invocation.
  // 指定需要传递给 go tool compile 命令的标记的列表
  
- installsuffix suffix
  a suffix to use in the name of the package installation directory,
    in order to keep output separate from default builds.
    If using the -race flag, the install suffix is automatically set to race
    or, if set explicitly, has _race appended to it.
    // 使当前的输出目录与默认的编译输出目录分离,此标记的值会作为结果文件的父目录名称的后缀
    
- ldflags 'flag list'
  arguments to pass on each go tool link invocation.
  // 指定需要传递给 go tool link 命令的标记的列表
  
- tags 'tag list'
  a list of build tags to consider satisfied during the build.
    See the documentation for the go/build package for
    more information about build tags.
    // 指定在实际编译期间需要受理的编译标签(也可被称为编译约束)的列表

-ldflags "-w -s" 选项目的是获取最小的二进制文件

$ go tool link --help
...
-s
    Omit the symbol table and debug information.
    // 关闭符号表生成和调试信息
-w
    Omit the DWARF symbol table.
    // 关闭 DWARP 调试信息,无法在二进制文件上使用 gdb 的特定功能如设置断点获取堆栈跟踪信息。

-gcflags "-N -l" 选项目的是在编译过程中禁止内联优化,加快编译速度减少开销。

$ go tool compile --help
...
-N
    Disable optimizations.
    // 禁止编译优化
-l
    Disable inlining.
    // 禁止内联,一定程度上减少可执行程序大小

参考