Go 常用命令

环境管理

  • Go版本管理: gvm(go version manager)
  • GOPATH管理: gvp(go version package)
  • 依赖版本管理: gpm(go package manager)

go build

用于编译指定的源码文件或代码包以及它们的依赖包。

import导入路径中的最后一个元素是路径名而不是包名,路径名可以和包名不一样,但同一个目录只能定义一个包(包对应的_test测试包除外)

编译包:

# 当前路径方式
cd src/foo && go build
# 包导入路径方式
go build foo bar
# 本地代码包路径方式
go build ./src/foo

go build 在编译只包含库源码文件的代码包时,只做检查性的编译,不会输出任何结果文件。如果编译的是main包,则会将编译结果放到执行命令的目录下。

编译源码文件:

# 指定源码文件使用文件路径
# 指定的多个源码文件必须属于同一个目录(包)
go build src/foo/foo1.go src/foo/foo2.go

当执行以上编译时,编译命令在分析参数的时候如果发现第一个参数是Go源码文件而不是代码包时,会在内部生成一个名为“command-line-arguments”的虚拟代码包。也就是当前的foo1.go foo2.go属于”command-line-arguments”包,而不是foo包,因此除了指定的源码文件和它们所依赖的包,其它文件(如foo3.go)不会被编译。

同样,对于库源码文件,build不会输出任何结果文件。对于main包的源文件,go build要求有且只能有一个main函数声明,并将生成结果(与指定的第一个源码文件同名)放在执行该命令的当前目录下。

构建与go build之上的其它命令(如go rungo install),在编译包或源码文件时,过程和特性是一样的。

常用选项:

选项 描述
-v 打印出那些被编译的代码包的名字。
-n 打印编译期间所用到的其它命令,但是并不真正执行它们。
-x 打印编译期间所用到的其它命令。注意它与-n标记的区别。
-a 强行对所有涉及到的代码包(包含标准库中的代码包)进行重新构建,即使它们已经是最新的了。
-work 打印出编译时生成的临时工作目录的路径,并在编译结束时保留它。在默认情况下,编译结束时会删除该目录。

go run

go run编译(通过go build)并运行命令源码文件(main package),查看过程:

go run -x -work src/main/main.go
# build 临时目录
WORK=/var/folders/n5/j8y6skrx1xn3_ls64gl1lrsmmp53rv/T/go-build979313546
# main.go依赖foo包  先编译foo包
mkdir -p $WORK/foo/_obj/
mkdir -p $WORK/
cd /Users/wudaijun/Work/test/src/foo
/usr/local/Cellar/go/1.7/libexec/pkg/tool/darwin_amd64/compile -o $WORK/foo.a -trimpath $WORK -p foo -complete -buildid cd61b5a9f3c8eba0f3088adca894fc9bf695826b -D _/Users/wudaijun/Work/test/src/foo -I $WORK -pack ./foo.go
# 在虚拟包 command-line-arguments 中编译 main.go
mkdir -p $WORK/command-line-arguments/_obj/
mkdir -p $WORK/command-line-arguments/_obj/exe/
cd /Users/wudaijun/Work/test/src/main
/usr/local/Cellar/go/1.7/libexec/pkg/tool/darwin_amd64/compile -o $WORK/command-line-arguments.a -trimpath $WORK -p main -complete -buildid 9131b7dd9f64a85bb423da7f8a7d408c089a23e8 -D _/Users/wudaijun/Work/test/src/main -I $WORK -I /Users/wudaijun/Work/test/pkg/darwin_amd64 -pack ./main.go
# 链接
cd .
/usr/local/Cellar/go/1.7/libexec/pkg/tool/darwin_amd64/link -o $WORK/command-line-arguments/_obj/exe/main -L $WORK -L /Users/wudaijun/Work/test/pkg/darwin_amd64 -w -extld=clang -buildmode=exe -buildid=9131b7dd9f64a85bb423da7f8a7d408c089a23e8 $WORK/command-line-arguments.a
# 从临时目录运行可执行文件
$WORK/command-line-arguments/_obj/exe/main
Call Foo()

可看到go run的执行结果都在WORK临时目录中完成,由于使用了-work选项,因此WORK目录会在go run执行完成后保留。go run只接受命令源文件而不接收包路径作为参数,并且不会在当前目录生成任何文件。

go install

go install只比go build多干一件事:安装编译后的结果文件到指定目录。

go test

1. 单元测试

go test编译指定包或源文件,并执行所在包对应的测试用例。一个符合规范的测试文件指:

  • 文件名必须是_test.go结尾的,这样在执行go test的时候才会执行到相应的代码
  • 你必须import testing这个包
  • 所有的测试用例函数必须是Test开头
  • 测试用例会按照源代码中写的顺序依次执行
  • 测试函数TestXxx()的参数是testing.T,我们可以使用该类型来记录错误或者是测试状态
  • 测试格式:func TestXxx (t *testing.T),Xxx部分可以为任意的字母数字的组合,但是- - 首字母不能是小写字母[a-z],例如Testingdiv是错误的函数名
  • 函数中通过调用testing.T的Error, Errorf, FailNow, Fatal, FatalIf方法,说明测试不通过,调用Log方法用来记录测试的信息

测试分为包内测试和包外测试,即测试源码文件可于被测试源码文件位于同一个包(目录),或者测试源码文件声明的包名可以是被测试包名+”_test”后缀。

2. 基准测试

基准测试也就是跑分测试,写法和单元测试差不多,只不过函数签名为BenchmarkXxx(b *testing.B),函数内通过 b.N 作为迭代次数,go test会自动调整这个值,得到合适的测试次数,然后算出每次迭代消耗的时间。

3. 执行测试

# 执行当前目录所在包的单元测试
go test . 
# 执行当前目录所在包的单元测试和基准测试(-bench 后面接正则匹配,'.'通配所有 Benchmark)
go test -bench . . 
# 执行当前目录所在包的 TestAbc 单元测试以及 BenchmarkAbc 基准测试
go test -run TestAbc -bench BenchmarkAbc . 

# 在当前目录生成 battle.test 二进制文件而不执行,支持 go build 的所有参数。如可通过 -o 参数指定输出文件
go test -c ngs/battle 
# 直接执行 test 二进制时,test flag 需要加上 'test.' 前缀
./battle.test -test.bench . 

# 以下两条命令等价 并且实际上,编译器也是分为这两步来做的
go test -bench . -cpuprofile cpu.prof .
go test -c -o my.test . && my.test -test.bench . -test.cpuprofile cpu.prof

# 如果要在 go test 时传入无需编译器加 'test.' 前缀的 flag,可将 flag 放在 -args 选项后:
go test -v -args -x -v
# 等价于:
pkg.test -test.v -x -v