go build [-o output] [-i] [build flag] [packages]

应该没有人不熟悉这个命令吧,这是go的编译命令,可以用来编译可执行程序或包。它会忽略_test.go结尾的文件,go编译器将它们识别为测试代码。

默认情况下,可执行程序编译成.exe文件,文件名是main.go所在的目录名。包编译结果会被丢弃,仅仅是检查它能编译通过。

-o参数用来指定编译结果输出位置,可以是文件,也可以是目录。目录是否存在是会影响命令执行结果的:

  • 如果目录存在,则将编译结果放到指定目录下。
  • 如果目录不存在,它会将目录的最后一部分识别为文件名。比如go build -o hello/world,结果是在hello目录下生成world文件,注意是名为world的文件,不是目录。那如果执行的是go build -o hello/world/,结果是会创建helloworld两个目录,注意是目录,随即退出,不会产生任何编译结果。

总结就是如果要指定编译输出目录,最好也指定一下文件名。比如go build -o /bin/out.exe

-i参数在编译时自动安装依赖。注意只是安装,不包括下载。说白了就是会对依赖包执行一遍go install

编译参数对于buildcleangetinstalllistruntest是一样的,因此后面将不会重复介绍。

  1. -a强制重新编译已更新的包
  2. -n打印执行的命令,但是并不真正执行
  3. -p nn是一个数字,表示编译或测试的并行程序数,默认为CPU核心数
  4. -race打开数据竞争检测。支持linux/amd64,freebsd/amd64,darwin/amd64,windows/amd64,linux/ppc64le和linux/arm64(仅48-bit VMA)
  5. -msan打开交互式内存优化。支持linux/amd64,linux/arm64,且C编译器为Clang/LLVM。在linux/arm64上,编译模式使用pie
  6. -v打印编译的包名(但不是每次都能打印出来,真奇怪?)
  7. -work打印临时工作目录名,并在编译结束后不删除临时工作目录
  8. -x打印并执行命令
  9. -asmflags '[pattern=]arg list'传递给asm工具的参数
  10. -buildmode mode编译模式,共8种。
  • -buildmode=archive将非main包编译为.a文件,main包将被忽略
  • -buildmode=c-archive必须是main包,将main包和依赖包编译为C文件,只有通过cgo导出的函数可以被调用
  • -buildmode=c-shared同上,区别是被编译成C共享库
  • -buildmode=default默认行为,main包被编译为可执行文件,非main包编译为.a文件
  • -buildmode=shared将所有非main包合并成一个共享库,非main包被忽略,共享库在使用-linkshared参数编译时使用
  • -buildmode=exe将main包编译为可执行文件,非main包被忽略
  • -buildmode=pie将main包编译为PIE,非main包被忽略。PIE是位置无关可执行程序
  • -buildmode=plugin将main包编译为Go插件,非main包被忽略

在AIX上,使用-buildmode=c-archive参数链接一个C程序时,必须传递给C编译器-Wl,-bnoobjreorder参数。

  1. -compile name指定编译器(gccgo或gc),默认是gc
  2. -gccgoflags '[pattern=]arg list'传递给编译器的参数,gccgo是Go的编译器
  3. -gcflags '[pattern=]arg list'传递给编译器的参数,gc也是Go的编译器
  • -B:禁用边界检查
  • -N:禁用优化
  • l:禁用函数内联
  • -u:禁用unsafe代码
  • -m:输出优化信息
  • -S:输出汇编代码
  1. -installsuffix suffix包安装目录名后缀,为的是与默认的编译输出分离。如果使用-race标志,后缀自动设置为race,如果指定了后缀,也会追加_race-msan和非默认的-buildmode也一样
  2. -ldflags '[pattern=]arg list'传递给go链接器的参数
  3. -linkshared编译将要链接到使用-buildmode=shared参数生成的共享库的代码
  4. -mod mode模块下载模式:只读,vender,mod。内容较多,这里就不展开了
  5. modcacherw让在模块缓存中新创建的目录为可读写,而不是只读
  6. -modfile file使用模块时,go.mod文件默认在模块跟目录。该参数可以指定使用另一个go.mod文件,同时也会在此目录下生成go.sum文件,注意,原来模块根目录下的go.mod文件不能删除。
  7. pkgdir dir指定一个安装和加载包的目录
  8. -tags tag,list其实就是编译约束,用逗号分隔,早期Go版本用空格分隔,现在已被丢弃,但是任然可以识别
  9. -trimpath从生成的可执行文件中删除文件系统路径。标准库将以“go”开头,模块变成path@version,或者如果使用GOPATH,就直接是import路径,而不是绝对路径。说白了就是要变成文件系统无关的
  10. -toolexec 'cmd args'用来调用工具链(如vet和asm)的程序,上例中,go命令不会直接运行asm,而是调用cmd args /path/to/asm <args>,它会使用cmd去运行asm

-asmflags-gccgoflags-gcflags-ldflags的参数以空格分隔,如果命令中包含空格,将参数包裹在单引号或双引号中。