gopl-zh.github.com/ch1/ch1-01.md
2016-04-03 17:23:09 +08:00

89 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 1.1. Hello, World
我们以现已成为传统的“hello world”案例来开始吧, 这个例子首次出现于1978年出版的C语言圣经[《The C Programming Language》](http://s3-us-west-2.amazonaws.com/belllabs-microsite-dritchie/cbook/index.html)[^1]。C语言是直接影响Go语言设计的语言之一。这个例子体现了Go语言一些核心理念。
<u><i>gopl.io/ch1/helloworld</i></u>
```go
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
```
Go是一门编译型语言Go语言的工具链将源代码及其依赖转换成计算机的机器指令[^2]。Go语言提供的工具都通过一个单独的命令`go`调用,`go`命令有一系列子命令。最简单的一个子命令就是run。这个命令编译一个或多个以.go结尾的源文件链接库文件并运行最终生成的可执行文件。本书使用$表示命令行提示符。)
```
$ go run helloworld.go
```
毫无意外,这个命令会输出:
```
Hello, 世界
```
Go语言原生支持Unicode它可以处理全世界任何语言的文本。
如果不只是一次性实验你肯定希望能够编译这个程序保存编译结果以备将来之用。可以用build子命令
```
$ go build helloworld.go
```
这个命令生成一个名为helloworld的可执行的二进制文件[^3],之后你可以随时运行它[^4],不需任何处理[^5]。
```
$ ./helloworld
Hello, 世界
```
本书中, 所有的示例代码上都有一行标记,利用这些标记, 可以从[gopl.io](http://gopl.io)网站上本书源码仓库里获取代码:
```
gopl.io/ch1/helloworld
```
执行 `go get gopl.io/ch1/helloworld` 命令,就会从网上获取代码,并放到对应目录中[^6]。2.6和10.7节有这方面更详细的介绍。
来讨论下程序本身。Go语言的代码通过**包**package组织包类似于其它语言里的库libraries或者模块modules。一个包由位于单个目录下的一个或多个.go源代码文件组成, 目录定义包的作用。每个源文件都以一条`package`声明语句开始,这个例子里就是`package main`, 表示该文件属于哪个包紧跟着一系列导入import的包之后是存储在这个文件里的程序语句。
Go的标准库提供了100多个包以支持常见功能如输入、输出、排序以及文本处理。比如`fmt`包,就含有格式化输出、接收输入的函数。`Println`是其中一个基础函数,可以打印以空格间隔的一个或多个值,并在最后添加一个换行符,从而输出一整行。
`main`包比较特殊。它定义了一个独立可执行的程序,而不是一个库。在`main`里的`main` *函数* 也很特殊,它是整个程序执行时的入口[^7]。`main`函数所做的事情就是程序做的。当然了,`main`函数一般调用其它包里的函数完成很多工作, 比如, `fmt.Println`
必须告诉编译器源文件需要哪些包,这就是`import`声明以及随后的`package`声明扮演的角色。hello world例子只用到了一个包大多数程序需要导入多个包。
必须恰当导入需要的包,缺少了必要的包或者导入了不需要的包,程序都无法编译通过。这项严格要求避免了程序开发过程中引入未使用的包[^8]。
`import`声明必须跟在文件的`package`声明之后。随后,则是组成程序的函数、变量、常量、类型的声明语句(分别由关键字`func`, `var`, `const`, `type`定义)。这些内容的声明顺序并不重要[^9]。这个例子的程序已经尽可能短了,只声明了一个函数, 其中只调用了一个其他函数。为了节省篇幅,有些时候, 示例程序会省略`package`和`import`声明,但是,这些声明在源代码里有,并且必须得有才能编译。
一个函数的声明由`func`关键字、函数名、参数列表、返回值列表(这个例子里的`main`函数参数列表和返回值都是空的)以及包含在大括号里的函数体组成。第五章进一步考察函数。
Go语言不需要在语句或者声明的末尾添加分号除非一行上有多条语句。实际上编译器会主动把特定符号后的换行符转换为分号, 因此换行符添加的位置会影响Go代码的正确解析[^10]。。举个例子, 函数的左括号`{`必须和`func`函数声明在同一行上, 且位于末尾,不能独占一行,而在表达式`x + y`中,可在`+`后换行,不能在`+`前换行。
Go语言在代码格式上采取了很强硬的态度。`gofmt`工具把代码格式化为标准格式[^12],并且`go`工具中的`fmt`子命令会对指定包, 否则默认为当前目录, 中所有.go源文件应用`gofmt`命令。本书中的所有代码都被gofmt过。你也应该养成格式化自己的代码的习惯。以法令方式规定标准的代码格式可以避免无尽的无意义的琐碎争执[^13]。更重要的是这样可以做多种自动源码转换如果放任Go语言代码格式这些转换就不大可能了。
很多文本编辑器都可以配置为保存文件时自动执行`gofmt`,这样你的源代码总会被恰当地格式化。还有个相关的工具,`goimports`,可以根据代码需要, 自动地添加或删除`import`声明。这个工具并没有包含在标准的分发包中,可以用下面的命令安装:
```
$ go get golang.org/x/tools/cmd/goimports
```
对于大多数用户来说下载、编译包、运行测试用例、察看Go语言的文档等等常用功能都可以用go的工具完成。10.7节详细介绍这些知识。
[^1]: 本书作者之一Brian W. Kernighan也是《The C Programming Language》一书的作者。
[^2]: 静态编译。
[^3]: Windows系统下生成的可执行文件是helloworld.exe增加了.exe后缀名。
[^4]: 在Windows系统下在命令行直接输入helloworld.exe命令运行。
[^5]: 因为静态编译,所以不用担心在系统库更新的时候冲突,幸福感满满。
[^6]: 需要先安装Git或Hg之类的版本管理工具并将对应的命令添加到PATH环境变量中。序言已经提及需要先设置好GOPATH环境变量下载的代码会放在`$GOPATH/src/gopl.io/ch1/helloworld`目录。
[^7]: C系语言差不多都这样。
[^8]: Go语言编译过程没有警告信息争议特性之一。
[^9]: 最好还是定一下规范。
[^10]: 比如行末是标识符、整数、浮点数、虚数、字符或字符串文字、关键字`break`、`continue`、`fallthrough`或`return`中的一个、运算符和分隔符`++`、`--`、`)`、`]`或`}`中的一个。
[^11]: 以+结尾的话不会被插入分号分隔符但是以x结尾的话则会被分号分隔符从而导致编译错误。
[^12]: 这个格式化工具没有任何可以调整代码格式的参数Go语言就是这么任性。
[^13]: 也导致了Go语言的TIOBE排名较低因为缺少撕逼的话题。