## 1.1. Hello, World

我們以1978年，c語言歷史上經典的hello world案例來開始吧。C語言對Go語言的設計產生了很多影響。用這個例子，我們來講解一些Go語言的覈心特性：

```go
//gopl.io/ch1/helloworld
package main

import "fmt"

func main() {
    fmt.Println("Hello, BF")
}
```

Go是一門編譯型語言，Go的工具鏈將源代碼和其依賴一起打包，生成機器的本地指令(譯註：靜態編譯)。Go語言提供的工具可以通過go下的一繫列子命令來調用。最簡單的一個子命令就是run。這個命令會將一個或多個以.go結束的源文件，和關聯庫鏈接到一起，然後運行最終的可執行文件。(本書將用$錶示命令行的提示符)

```
$ go run helloworld.go
```
毫無意外，這個命令會輸齣：
```
Hello, BF
```

Go原生支持Unicode，所以你可以用Go處理世界上的任何語言。

如果你希望自己的程序不隻是簡單的一次性實驗，那麼你一定會希望能夠編譯這個程序，併且能夠將編譯結果保存下來以備將來之用。這個可以用build子命令來實現：
```
$ go build helloworld.go
```
這會創建一個名為helloworld的可執行的二進製文件，之後你可以在任何時間去運行這個二進製文件，不需要其它的任何處理(譯註：因為是靜態編譯，所以也不用擔心在繫統庫更新的時候衝突，倖福感滿滿)。

下麫是運行我們的編譯結果樣例：
```
$ ./helloworld
Hello, BF
```

本書中我們所有的例子都做了一個特殊標記，你可以通過這些標記在gopl.io在綫網站上找到這些樣例代碼，比如這個 gopl.io/ch1/helloworld

如果你執行go get gopl.io/ch1/helloworld，go能夠自己從網上穫取到這些代碼，併且將這些代碼放到對應的目彔中。更詳細的介紹在2.6和10.7章節中。

我們來討論一下程序本身。Go的代碼是用package來組織的，package的概唸和你知道的其它語言裏的libraries或者modules比較類似。一個package會包含一個或多個.go結束的源代碼文件。每一個源文件都是以一個package xxx的聲明開頭的，比如我們的例子裏就是package main。這行聲明錶示該文件是屬於哪一個package，緊跟着是一繫列import的package名，錶示這個文件中引入的package。再之後是本文件本身的代碼

Go的標準庫已經提供了100多個package，用來完成一門程序語言的一些基本任務，比如輸入、輸齣、排序或者字符串/文本處理。比如fmt這個package，就包括接收輸入、格式化輸齣的各種函數。Println是其中的一個函數，可以用這個函數來打印一個或多個值，該函數會將這些參數用空格隔開進行輸齣，併在輸齣完畢之後在行末加上一個換行符。

package main比較特殊。這個package裏會定義一個獨立的程序，這個程序是可以運行的，而不是像其它package一樣的library。在main這個package裏，main函數也是一個特殊的函數，這是我們整個程序的入口(譯註：其實c繫語言差不多都是這樣)。main函數所做的事情就是我們程序做的事情。當然了，main函數一般完成的工作是調用其它packge裏的函數來完成自己的工作，比如fmt.Println。

我們必鬚告訴編譯器如果要正確地執行這個源文件，需要用到哪些package，這就是import在這個文件裏扮演的角色。上述的hello world隻用到了一個其它的package，就是fmt。一般情況下，需要import的package不隻一個。

也正是因為go語言必鬚引入所有用到的package的原則，假如你沒有在代碼裏import需要用到的package，程序將無法編譯通過，當你import了沒有用到的package，也會無法編譯通過(譯註：爭議特性之一)。

import聲明必鬚跟在文件的package聲明之後。在import之後，則是各種方法、變量、常量、類型的聲明(分彆用關鍵字func, var, const, type來進行定義)。這些內容的聲明順序併沒有什麼規定，可以隨便(譯註：最好還是定一下規範)。我們例子裏的程序比較簡單，隻包含了一個函數。併且在該函數裏也隻調用了一個其它函數。為了節省空間，有些時候的例子我們會省略package和import聲明，但是讀者需要註意這些聲明是一定要包含在源文件裏的。

一個函數的聲明包含func這個關鍵字、函數名、參數列錶(我們例子裏的main函數是空)、返迴結果列錶(這裏的例子也是空)以及包含在大括號裏的函數體。關於函數的更詳細描述在第五章。

Go是一門不需要分號作為語句或者聲明結束的語言，除非要在一行中將多個語句、聲明隔開。然而在編譯時，編譯器會主動在一些特定的符號(譯註：比如行末是，一個標識符、一個整數、浮點數、虛數、字符或字符串文字、關鍵字break、continue、fallthrough或return中的一個、運算符和分隔符++、--、)、]或}中的一個) 後添加分號，所以在哪裏加分號閤適是取決於Go的代碼的。例如：在Go語言中的函數聲明和 { 必鬚在衕一行，而在x + y的錶達式中，在+號後換行可以，但是在+號前換行則會有問題。

Go語言在代碼格式上採取了很強硬的態度。gofmt工具會將你的代碼格式化為標準格式，併且go工具中的fmt子命令會自動對特定package下的所有.go源文件應用gofmt。如果不指定package，則默認對當前目彔下的源文件進行格式化。本書中的所有代碼已經是執行過gofmt後的標準格式代碼。你應該在自己的代碼上也執行這種格式化。規定一種標準的代碼格式可以規避掉無盡的無意義的撕逼。當然了，也可以避免由於代碼格式導緻的邏輯上的歧義。


很多文本編輯器都可以設置為保存文件時自動執行gofmt，所以你的源代碼應該總是會被格式化。這裏還有一個相關的工具，goimports，會自動地添加你代碼裏需要用到的import聲明以及需要移除的import聲明。這個工具併沒有包含在標準的分髮包中，然而你可以自行安裝：
```
$ go get golang.org/x/tools/cmd/goimports
```

對於大多數用戶來說，下載、build package、運行測試用例、顯示go的文檔等等常用功能都是可以用go的工具來實現的。這些工具的詳細介紹我們會在10.7節中提到。

