在Go语言中,我们很多操作都是通过go命令进行的,比如我们要执行go文件的编译,就需要使用go build命令,除了build命令之外,还有很多常用的命令,这一次我们就统一进行介绍,对常用命令有一个了解,这样我们就可以更容易地开发我们的Go程序了。


Go 开发工具概览

go这个工具,别看名字短小,其实非常强大,是一个强大的开发工具,让我们打开终端,看看这个工具有哪些能力。

~goGoisatoolformanagingGosourcecode.Usage:gocommand[arguments]Thecommandsare:buildcompilepackagesanddependenciescleanremoveobjectfilesdocshowdocumentationforpackageorsymbolenvprintGoenvironmentinformationbugstartabugreportfixrungotoolfixonpackagesfmtrungofmtonpackagesourcesgenerategenerateGofilesbyprocessingsourcegetdownloadandinstallpackagesanddependenciesinstallcompileandinstallpackagesanddependencieslistlistpackagesruncompileandrunGoprogramtesttestpackagestoolrunspecifiedgotoolversionprintGoversionvetrungotoolvetonpackagesUse"gohelp[command]"formoreinformationaboutacommand.Additionalhelptopics:ccallingbetweenGoandCbuildmodedescriptionofbuildmodesfiletypefiletypesgopathGOPATHenvironmentvariableenvironmentenvironmentvariablesimportpathimportpathsyntaxpackagesdescriptionofpackageliststestflagdescriptionoftestingflagstestfuncdescriptionoftestingfunctionsUse"gohelp[topic]"formoreinformationaboutthattopic.

可以发现,go支持的子命令很多,同时还支持查看一些【主题】。我们可以使用go help [command]或者go help [topic]查看一些命令的使用帮助,或者关于某个主题的信息。大部分go的命令,都是接受一个全路径的包名作为参数,比如我们经常用的go build


go build

go build,是我们非常常用的命令,它可以启动编译,把我们的包和相关的依赖编译成一个可执行的文件。

usage:gobuild[-ooutput][-i][buildflags][packages]

go build的使用比较简洁,所有的参数都可以忽略,直到只有go build,这个时候意味着使用当前目录进行编译,下面的几条命令是等价的:

gobuildgobuild.gobuildhello.go

以上这三种写法,都是使用当前目录编译的意思。因为我们忽略了packages,所以自然就使用当前目录进行编译了。从这里我们也可以推测出,go build本质上需要的是一个路径,让编译器可以找到哪些需要编译的go文件。packages其实是一个相对路径,是相对于我们定义的GOROOTGOPATH这两个环境变量的,所以有了packages这个参数后,go build就可以知道哪些需要编译的go文件了。

gobuildflysnow.org/tools

这种方式是指定包的方式,这样会明确地编译我们这个包。当然我们也可以使用通配符。

gobuildflysnow.org/tools/...

3个点表示匹配所有字符串,这样go build就会编译tools目录下的所有包。

讲到go build编译,不能不提跨平台编译,Go提供了编译链工具,可以让我们在任何一个开发平台上,编译出其他平台的可执行文件。

默认情况下,都是根据我们当前的机器生成的可执行文件,比如你的是Linux 64位,就会生成Linux 64位下的可执行文件,比如我的Mac;可以使用go env查看编译环境,以下截取重要的部分。

~goenvGOARCH="amd64"GOEXE=""GOHOSTARCH="amd64"GOHOSTOS="darwin"GOOS="darwin"GOROOT="/usr/local/go"GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"

注意里面两个重要的环境变量GOOS和GOARCH,其中GOOS指的是目标操作系统,它的可用值为:

darwin

freebsd

linux

windows

android

dragonfly

netbsd

openbsd

plan9

solaris

一共支持10种操作系统。GOARCH指的是目标处理器的架构,目前支持的有:

arm

arm64

386

amd64

ppc64

ppc64le

mips64

mips64le

s390x

一共支持9种处理器的架构,GOOS和GOARCH组合起来,支持生成的可执行程序种类很多,具体组合参考:

https://golang.org/doc/install/source#environment

如果我们要生成不同平台架构的可执行程序,只要改变这两个环境变量就可以了,比如要生成Linux 64位的程序,命令如下:

GOOS=linuxGOARCH=amd64gobuildflysnow.org/hello

前面两个赋值,是更改环境变量,这样的好处是只针对本次运行有效,不会更改我们默认的配置。

以上这些用法差不多够我们用的了,更多关于go build的用户可以通过以下命令查看:

gohelpbuild

go clean

在我们使用go build编译的时候,会产生编译生成的文件,尤其是在我们签入代码的时候,并不想把我们生成的文件也签入到我们的Git代码库中,这时候我们可以手动删除生成的文件,但是有时候会忘记,也很麻烦,不小心还是会提交到Git中。要解决这个问题,我们可以使用go clean,它可以清理我们编译生成的文件,比如生成的可执行文件,生成obj对象等。

usage:goclean[-i][-r][-n][-x][buildflags][packages]

用法和go build基本一样,这样不再进行详细举例演示,可以参考go build的使用,更多关于go clean的使用,可以使用如下命令查看:

gohelpclean

go run

go build是先编译,然后我们再执行可以执行文件来运行我们的程序,需要两步。go run这个命令就是可以把这两步合成一步的命令,节省了我们录入的时间,通过go run命令,我们可以直接看到输出的结果。

~gohelprunusage:gorun[buildflags][-execxprog]gofiles...[arguments...]RuncompilesandrunsthemainpackagecomprisingthenamedGosourcefiles.AGosourcefileisdefinedtobeafileendinginaliteral".go"suffix.Bydefault,'gorun'runsthecompiledbinarydirectly:'a.outarguments...'.Ifthe-execflagisgiven,'gorun'invokesthebinaryusingxprog:'xproga.outarguments...'.Ifthe-execflagisnotgiven,GOOSorGOARCHisdifferentfromthesystemdefault,andaprogramnamedgo_$GOOS_$GOARCH_execcanbefoundonthecurrentsearchpath,'gorun'invokesthebinaryusingthatprogram,forexample'go_nacl_386_execa.outarguments...'.Thisallowsexecutionofcross-compiledprogramswhenasimulatororotherexecutionmethodisavailable.Formoreaboutbuildflags,see'gohelpbuild'.

go run命令需要一个go文件作为参数,这个go文件必须包含main包和main函数,这样才可以运行,其他的参数和go build差不多。 在运行go run的时候,如果需要的话,我们可以给我们的程序传递参数,比如:

packagemainimport("fmt""os")funcmain(){fmt.Println("输入的参数为:",os.Args[1])}

打开终端,输入如下命令执行:

gorunmain.go12

这时候我们就可以看到输出:

输入的参数为:12

go env

在前面讲go build的时候,我们使用了go env命令查看了我们当前的go环境信息。

hellogohelpenvusage:goenv[var...]EnvprintsGoenvironmentinformation.Bydefaultenvprintsinformationasashellscript(onWindows,abatchfile).Ifoneormorevariablenamesisgivenasarguments,envprintsthevalueofeachnamedvariableonitsownline.

使用go env查看我们的go环境信息,便于我们进行调试,排错等,因为有时候我们会遇到一些莫名其妙的问题,比如本来在Mac上开发,怎么编译出一个Linux的可执行文件等,遇到这类问题时,先查看我们的go环境信息,看看有没有哪里配置错了,一步步排错。


go install

从其名字上我们不难猜出这个命令是做什么的,它和go build类似,不过它可以在编译后,把生成的可执行文件或者库安装到对应的目录下,以供使用。

hellogohelpinstallusage:goinstall[buildflags][packages]Installcompilesandinstallsthepackagesnamedbytheimportpaths,alongwiththeirdependencies.

它的用法和go build差不多,如果不指定一个包名,就使用当前目录。安装的目录都是约定好的,如果生成的是可执行文件,那么安装在$GOPATH/bin目录下;如果是可引用的库,那么安装在$GOPATH/pkg目录下。


go get

go get命令,可以从网上下载更新指定的包以及依赖的包,并对它们进行编译和安装。

gogetgithub.com/spf13/cobra

以上示例,我们就可以从github上直接下载这个go库到我们GOPATH工作空间中,以供我们使用。下载的是整个源代码工程,并且会根据它们编译和安装,和执行go install类似。

go get支持大多数版本控制系统(VCS),比如我们常用的git,通过它和包依赖管理结合,我们可以在代码中直接导入网络上的包以供我们使用。

如果我们需要更新网络上的一个go工程,加-u标记即可。

goget-ugithub.com/spf13/cobra

类似的,启用-v标记,可以看到下载的进度以及更多的调试信息。关于go get命令的更多用法,可以使用如下命令查看:

gohelpget

go fmt

这是go提供的最帅的一个命令了,它可以格式化我们的源代码的布局和Go源代码一样的风格,也就是统一代码风格,这样我们再也不用为大括号要不要放到行尾还是另起一行,缩进是使用空格还是tab而争论不休了,都给我们统一了。

funcmain(){fmt.Println("输入的参数为:",os.Args[1])}

比如以上代码,我们执行go fmt格式化后,会变成如下这样:

funcmain(){fmt.Println("输入的参数为:",os.Args[1])}

go fmt也是接受一个包名作为参数,如果不传递,则使用当前目录。go fmt会自动格式化代码文件并保存,它本质上其实是调用的gofmt -l -w这个命令,我们看下gofmt的使用帮助。

hellogofmt-husage:gofmt[flags][path...]-cpuprofilestringwritecpuprofiletothisfile-ddisplaydiffsinsteadofrewritingfiles-ereportallerrors(notjustthefirst10ondifferentlines)-llistfileswhoseformattingdiffersfromgofmt's-rstringrewriterule(e.g.,'a[b:len(a)]->a[b:]')-ssimplifycode-wwriteresultto(source)fileinsteadofstdout

go fmt为我们统一了代码风格,这样我们在整个团队协作中发现,所有代码都是统一的,像一个人写的一样。所以我们的代码在提交到git库之前,一定要使用go fmt进行格式化,现在有很多编辑器可以在保存的时候,自动帮我们格式化代码。


go vet

这个命令不会帮助开发人员写代码,但是它也很有用,因为它会帮助我们检查我们代码中常见的错误。

Printf这类的函数调用时,类型匹配了错误的参数。

定义常用的方法时,方法签名错误。

错误的结构标签。

没有指定字段名的结构字面量。

packagemainimport("fmt")funcmain(){fmt.Printf("哈哈",3.14)}

这个例子是一个明显错误的例子,新手经常会犯,这里我们忘记输入了格式化的指令符,这种编辑器是检查不出来的,但是如果我们使用go vet就可以帮我们检查出这类常见的小错误。

hellogovetmain.go:8:noformattingdirectiveinPrintfcall

看,提示多明显。其使用方式和go fmt一样,也是接受一个包名作为参数。

usage:govet[-n][-x][buildflags][packages]

养成在代码提交或者测试前,使用go vet检查代码的好习惯,可以避免一些常见问题。

go test

该命令用于Go的单元测试,它也是接受一个包名作为参数,如果没有指定,使用当前目录。go test运行的单元测试必须符合go的测试要求。

写有单元测试的文件名,必须以_test.go结尾。

测试文件要包含若干个测试函数。

这些测试函数要以Test为前缀,还要接收一个*testing.T类型的参数。

packagemainimport"testing"funcTestAdd(t*testing.T){ifAdd(1,2)==3{t.Log("1+2=3")}ifAdd(1,1)==3{t.Error("1+1=3")}}

这是一个单元测试,保存在main_test.go文件中,对main包里的Add(a,b int)函数进行单元测试。 如果要运行这个单元测试,在该文件目录下,执行go test即可。

hellogotestPASSokflysnow.org/hello0.006s

以上是打印输出,测试通过。更多关于go test命令的使用,请通过如下命令查看。

gohelptest

以上这些,主要介绍的是go这个开发工具常用的命令,熟悉了之后可以帮助我们更好地开发编码。