2015-12-09 07:45:11 +00:00
## 1.1. Hello, World
2015-12-22 02:37:13 +00:00
我們以1978年齣版的C語言聖經《The C Programming Language》中經典的“hello world”案例來開始吧( 譯註: 本書作者之一Brian W. Kernighan也是C語言聖經一書的作者) 。C語言對Go語言的設計産生了很多影響。用這個例子, 我們來講解一些Go語言的覈心特性:
2015-12-09 07:45:11 +00:00
```go
//gopl.io/ch1/helloworld
package main
import "fmt"
func main() {
2015-12-22 02:37:13 +00:00
fmt.Println("Hello, 世界")
2015-12-09 07:45:11 +00:00
}
```
2015-12-22 02:37:13 +00:00
Go是一門編譯型語言, Go語言的工具鏈將源代碼和其依賴一起打包, 生成機器的本地指令(譯註:靜態編譯)。Go語言提供的工具可以通過go命令下的一繫列子命令來調用。最簡單的一個子命令就是run。這個命令會將一個或多個文件名以.go結尾的源文件, 和關聯庫鏈接到一起, 然後運行最終的可執行文件。( 本書將用$表示命令行的提示符。)
2015-12-09 07:45:11 +00:00
```
$ go run helloworld.go
```
2015-12-22 02:37:13 +00:00
2015-12-09 07:45:11 +00:00
毫無意外,這個命令會輸齣:
2015-12-22 02:37:13 +00:00
2015-12-09 07:45:11 +00:00
```
2015-12-22 02:37:13 +00:00
Hello, 世界
2015-12-09 07:45:11 +00:00
```
2015-12-22 02:37:13 +00:00
Go語言原生支持Unicode標準, 所以你可以用Go語言處理世界上的任何自然語言。
2015-12-09 07:45:11 +00:00
2015-12-18 06:49:31 +00:00
如果你希望自己的程序不隻是簡單的一次性實驗, 那麽你一定會希望能夠編譯這個程序, 併且能夠將編譯結果保存下來以備將來之用。這個可以用build子命令來實現:
2015-12-22 02:37:13 +00:00
2015-12-09 07:45:11 +00:00
```
$ go build helloworld.go
```
2015-12-22 02:37:13 +00:00
這會創建一個名爲helloworld的可執行的二進製文件( 譯註: 在Windows繫統下生成的可執行文件是helloworld.exe, 增加了.exe後綴名) , 之後你可以在任何時間去運行這個二進製文件, 不需要其它的任何處理(譯註:因爲是靜態編譯,所以也不用擔心在繫統庫更新的時候衝突,幸福感滿滿)。
下面是運行我們的編譯結果樣例( 譯註: 在Windows繫統下在命令行直接輸入helloworld.exe命令運行) :
2015-12-09 07:45:11 +00:00
```
$ ./helloworld
2015-12-22 02:37:13 +00:00
Hello, 世界
2015-12-09 07:45:11 +00:00
```
2015-12-22 02:37:13 +00:00
本書中我們所有的例子都做了一個特殊標記,你可以通過這些標記在 http://gopl.io 在線網站上找到這些樣例代碼,比如這個
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
```
gopl.io/ch1/helloworld
```
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
如果你執行 `go get gopl.io/ch1/helloworld` 命令, go命令能夠自己從網上穫取到這些代碼( 譯註: 需要先安裝Git或Hg之類的版本管理工具, 併將對應的命令添加到PATH環境變量中) , 併且將這些代碼放到對應的目録中( 譯註: 序言已經提及, 需要先設置好GOPATH環境變量, 下載的代碼會放在 $GOPATH/src/gopl.io/ch1/helloworld 目録) 。更詳細的介紹在2.6和10.7章節中。
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
我們來討論一下程序本身。Go語言的代碼是通過package來組織的, package的概念和你知道的其它語言里的libraries或者modules概念比較類似。一個package會包含一個或多個.go結束的源代碼文件。每一個源文件都是以一個package xxx的聲明語句開頭的, 比如我們的例子里就是package main。這行聲明語句表示該文件是屬於哪一個package, 緊跟着是一繫列import的package名, 表示這個文件中引入的package。再之後是本文件本身的代碼。
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
Go的標準庫已經提供了100多個package, 用來完成一門程序語言的一些常見的基本任務, 比如輸入、輸齣、排序或者字符串/文本處理。比如fmt這個package, 就包括接收輸入、格式化輸齣的各種函數。Println是其中的一個常用的函數, 可以用這個函數來打印一個或多個值, 該函數會將這些參數用空格隔開進行輸齣, 併在輸齣完畢之後在行末加上一個換行符。
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
package main是一個比較特殊的package。這個package里會定義一個獨立的程序, 這個程序是可以運行的, 而不是像其它package一樣對應一個library。在main這個package里, main函數也是一個特殊的函數, 這是我們整個程序的入口( 譯註: 其實C繫語言差不多都是這樣) 。main函數所做的事情就是我們程序做的事情。當然了, main函數一般是通過是調用其它packge里的函數來完成自己的工作, 比如fmt.Println。
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
我們必鬚告訴編譯器如何要正確地執行這個源文件, 需要用到哪些package, 這就是import在這個文件里扮演的角色。上述的hello world例子隻用到了一個其它的package, 就是fmt。一般情況下, 需要import的package可能不隻一個。
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
這也正是因爲go語言必鬚引入所有要用到的package的原則, 假如你沒有在代碼里import需要用到的package, 程序將無法編譯通過, 同時當你import了沒有用到的package, 也會無法編譯通過( 譯註: Go語言編譯過程沒有警告信息, 爭議特性之一) 。
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
import聲明必鬚跟在文件的package聲明之後。在import語句之後, 則是各種方法、變量、常量、類型的聲明語句(分别用關鍵字func, var, const, type來進行定義)。這些內容的聲明順序併沒有什麽規定,可以隨便調整順序(譯註:最好還是定一下規范)。我們例子里的程序比較簡單, 隻包含了一個函數。併且在該函數里也隻調用了一個其它函數。爲了節省空間, 有些時候的例子我們會省略package和import聲明, 但是讀者需要註意這些聲明是一定要包含在源文件里的。
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
一個函數的聲明包含func這個關鍵字、函數名、參數列表、返迴結果列表( 我們例子里的main函數參數列表和返迴值都是空的) 以及包含在大括號里的函數體。關於函數的更詳細描述在第五章。
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
Go語言是一門不需要分號作爲語句或者聲明結束的語言, 除非要在一行中將多個語句、聲明隔開。然而在編譯時, 編譯器會主動在一些特定的符號( 譯註: 比如行末是, 一個標識符、一個整數、浮點數、虛數、字符或字符串文字、關鍵字break、continue、fallthrough或return中的一個、運算符和分隔符++、--、)、]或}中的一個) 後添加分號, 所以在哪里加分號合適是取決於Go語言代碼的。例如: 在Go語言中的函數聲明和 { 大括號必鬚在同一行, 而在x + y這樣的表達式中, 在+號後換行可以,但是在+號前換行則會有問題(譯註:以+結尾的話不會被插入分號分隔符, 但是以x結尾的話則會被分號分隔符, 從而導致編譯錯誤) 。
2015-12-09 07:45:11 +00:00
2015-12-22 02:37:13 +00:00
Go語言在代碼格式上采取了很強硬的態度。gofmt工具會將你的代碼格式化爲標準格式( 譯註: 這個格式化工具沒有任何可以調整代碼格式的參數, Go語言就是這麽任性) , 併且go工具中的fmt子命令會自動對特定package下的所有.go源文件應用gofmt工具格式化。如果不指定package, 則默認對當前目録下的源文件進行格式化。本書中的所有代碼已經是執行過gofmt後的標準格式代碼。你應該在自己的代碼上也執行這種格式化。規定一種標準的代碼格式可以規避掉無盡的無意義的撕逼( 譯註: 也導致了Go語言的TIOBE排名較低, 因爲缺少撕逼的話題) 。當然了, 這可以避免由於代碼格式導致的邏輯上的歧義。
2015-12-09 07:45:11 +00:00
2015-12-18 06:49:31 +00:00
很多文本編輯器都可以設置爲保存文件時自動執行gofmt, 所以你的源代碼應該總是會被格式化。這里還有一個相關的工具, goimports, 會自動地添加你代碼里需要用到的import聲明以及需要移除的import聲明。這個工具併沒有包含在標準的分發包中, 然而你可以自行安裝:
2015-12-09 07:45:11 +00:00
```
$ go get golang.org/x/tools/cmd/goimports
```
2015-12-22 02:37:13 +00:00
對於大多數用戶來説, 下載、build package、運行測試用例、顯示Go語言的文檔等等常用功能都是可以用go的工具來實現的。這些工具的詳細介紹我們會在10.7節中提到。
2015-12-09 07:45:11 +00:00