
1.3 Go命令集
Go提供了许多开箱即用的开发工具,包括编译器、代码格式化工具、linter(代码风格检查工具)、依赖项管理工具、测试运行工具等。在学习如何构建高质量且符合Go语言惯例的应用程序时,我们将在全书中探讨这些工具。现在我们从用于构建Go代码的工具开始,并使用go
命令构建一个简单的应用程序。
1.3.1 go run和go build
go
提供了两个类似的命令:go run
和go build
。它们都需要一个Go文件、一个Go文件列表或一个包的名称。我们将创建一个简单的程序,并看看在使用这些命令时会发生什么。
go run
我们先开始学习go run
。创建名为ch1的目录,打开文本编辑器,输入以下文本,然后将其保存在ch1中名为hello.go的文件里。

保存文件后,打开控制台或命令提示符,输入:

你会看到在控制台中打印出了Hello, world!
。如果运行go run
命令后查看目录内部,你会发现那里没有保存任何二进制文件,目录中唯一的文件是刚刚创建的hello.go文件。你可能会感到奇怪,Go不是一种编译型语言吗?这到底是怎么回事?
事实上,go run
命令确实会将你的代码编译成二进制文件。然而,二进制文件被创建在一个临时目录中。go run
命令生成二进制文件,并从临时目录中执行二进制文件,然后在程序结束后删除二进制文件。这使得go run
命令可以用于测试简短程序或将Go当作脚本语言使用。
当你想把Go程序当作一个脚本来处理,并立即运行源代码时,请使用
go run
。
go build
通常,当你打算构建一个可执行文件供以后使用时,可以使用go build
命令。在控制台的下一行输入:

这将在当前目录下创建一个名为hello
的可执行文件(或Windows下的hello.exe)。运行它,你会立即看到屏幕上打印出Hello, world!
。
二进制文件的名称与传入的文件或软件包的名称一致。如果想为你的应用程序取一个其他的名字,或者想把它存储在不同的位置,可以使用-o
标志。例如,如果想把代码编译成名为“hello_world”的二进制文件,可以使用:

大多数情况下,你要做的就是使用
go build
创建一个二进制文件,并发布给其他人使用。
1.3.2 获取第三方Go工具
虽然有些人选择将Go程序作为预编译的二进制文件发布,但用Go编写的工具也可以从源代码构建,并通过go install
命令安装到你的GO工作空间中。
Go的代码发布方法与其他大多数语言略有不同。Go开发者并不依赖于集中托管服务,比如Java的Maven Central或JavaScript的NPM注册分发服务。相反,他们通过源代码库共享项目。go install
命令接受一个参数,即你期望安装的项目的源代码库的位置,后面是@
和你想要的工具版本(如果你只想获得最新版本,请使用@latest
)。然后它就会下载、编译该工具并将其安装到$GOPATH/bin目录下。
让我们来看一个简单的例子。有一个很棒的Go工具叫hey
,它可以对HTTP服务端进行负载测试。你可以把它指向测试的网站或应用程序。用go install
命令安装hey
的代码如下所示:

这样就可以下载hey
及其所有依赖项,构建程序,并将二进制文件安装到$GOPATH/bin目录下。
我们将在9.7节中讲到,Go代码库的内容缓存在代理服务器中。根据代码库和
GOPROXY
环境变量中的值,go install
可以从代理服务器下载,也可以直接从代码库下载。如果go install
直接从代码库下载,还需要在计算机上安装其他命令行工具。例如,必须安装Git才能从GitHub下载。
现在我们已经构建并安装了hey,运行它:

如果你已经安装了一个工具,并希望将其更新到新版本,请使用指定的新版本或使用@latest
重新运行go install
:

当然,你不需要把用Go编写的工具保存在Go的工作空间,它们是常规的可执行二进制文件,可以存储在计算机的任何位置。同样,也不需要使用go install
分发用Go编写的程序,你可以提供一个二进制文件用于下载。不过,go install
是一种非常方便的Go程序分发方式。
1.3.3 代码格式化
Go的主要设计目标之一是创建一种能够高效编写代码的语言。这意味着要有简单的语法和快速的编译器,也促使Go的作者重新考虑代码的格式。大多数语言在代码的编排方式上都有很大的灵活性,而Go则不然。强制使用标准格式使得编写操作源代码的工具变得非常容易。这简化了编译器,并允许创建一些用于生成代码的智能工具。
另外一个好处是,开发者在格式之争上一直浪费了大量的时间。由于Go定义了一种标准的格式化代码的方式,Go开发者就避免了关于大括号风格与缩进风格的争论。例如,Go程序使用tab来缩进,如果开头的括号与代码块起始的声明或命令不在同一行,这就是语法错误。
许多Go开发者认为,Go团队定义标准格式是为了避免开发者之间的争论,后来才发现工具的优势。然而,Russ Cox曾公开表示(https://oreil.ly/rZEUv),更好的工具化正是他最初的动机。
Go开发工具中包含命令go fmt
,它可以自动重新格式化代码,使其符合标准格式。它的作用是修正缩进的固定空格,排列结构中的字段,并确保运算符周围有适当的间距。
有一个增强版的go fmt
叫作goimports
,它也可以清理导入语句。它将导入语句按字母顺序排列,删除未使用的导入语句,并尝试猜测任何未指定的导入。它的猜测有时是不准确的,所以需要更正导入语句。
可以使用命令go install golang.org/x/tools/cmd/goimports@latest
下载goimports
。可以用以下命令在项目中运行它:

-l
标志告诉goimports
将格式不正确的文件打印到控制台。-w
标志告诉goimports
在原路径修改文件。.
标志指定要扫描的文件:当前目录及其所有子目录中的所有文件。
分号插入规则
由于分号插入规则,go fmt
命令不能修正错误行上的大括号。与C语言或Java一样,Go也要求在每条语句的末尾都加一个分号。然而,Go开发者无须自行添加分号,Go编译器会按照Effective Go(https://oreil.ly/hTOHU)中描述的规则添加分号。
如果换行之前的最后一个标记是以下任何一种,则词法分析器(lexer)会在该标记后插入一个分号:
- 标识符,包括int和float64等词
- 基本字面量,如数字或字符串常量
- 以下标记之一:break、continue、fallthrough、return、++、--、)或}。
有了这个简单的规则,就能知道为什么将括号放置在不正确的位置会导致错误。如果你的代码如下所示:

分号插入规则在func main()
行末尾看到“)”,并将其转化为:

这并不符合Go语法。
分号插入规则使Go编译器更简单、更快捷,同时它强制执行一种编码风格。这种做法非常明智。
编译代码前一定要先运行
go fmt
或goimports
!