什么是 Go?來(lái)自其網(wǎng)站 [13] 的介紹:
Go 編程語(yǔ)言是一個(gè)使得程序員更加有效率的開(kāi)源項(xiàng)目。Go 是有表達(dá)力、簡(jiǎn)潔、清晰和有效率的。它的并行機(jī)制使其很容易編寫(xiě)多核和網(wǎng)絡(luò)應(yīng)用,而新奇的類型系統(tǒng)允許構(gòu)建有彈性的模塊化程序。Go 編譯到機(jī)器碼非??焖?,同時(shí)具有便利的垃圾回收和強(qiáng)大的運(yùn)行時(shí)反射。它是快速的、靜態(tài)類型編譯語(yǔ)言,但是感覺(jué)上是動(dòng)態(tài)類型的,解釋型語(yǔ)言。
Go 1 是 Go 語(yǔ)言的第一個(gè)穩(wěn)定發(fā)布版本。本文檔的所有練習(xí)都工作于 Go 1 – 如果不能 工作,那就一定是 bug。
本書(shū)使用了下面的約定:
Go 已經(jīng)有大量的文檔。例如 Go Tutorial [12] 和 Effective Go [8]。網(wǎng)站http://golangorg/doc/ 也是絕佳的起點(diǎn)。雖然并不一定要閱讀這些文檔,但是強(qiáng)烈建議這么做。 Go 1 通過(guò)叫做 go doc 的標(biāo)準(zhǔn)程序提供其文檔。如果你想了解內(nèi)建相關(guān)(參閱下一章“運(yùn)算符和內(nèi)建函數(shù)” 小節(jié))的文檔,可以像這樣獲取:
% go doc builtin
在第3 章解釋了如何構(gòu)造你自己的包的文檔。有一些特性讓 Go 與眾不同。
Go 努力保持小并且優(yōu)美,你可以在短短幾行代碼里做許多事情;
Go 讓函數(shù)很容易成為非常輕量的線程。這些線程在 Go 中被叫做 goroutines b;
這些 goroutines 之間的通訊由 channel[18, 25] 完成;
編譯很快,執(zhí)行也很快。目標(biāo)是跟 C 一樣快。編譯時(shí)間用秒計(jì)算;
當(dāng)轉(zhuǎn)換一個(gè)類型到另一個(gè)類型的時(shí)候需要顯式的轉(zhuǎn)換并遵循嚴(yán)格的規(guī)則。Go 有垃圾收集,在 Go 中無(wú)須 free(),語(yǔ)言會(huì)處理這一切;
Go 程序可以被格式化為程序員希望的(幾乎)任何形式,但是官方格式是存在的。標(biāo)準(zhǔn)也非常簡(jiǎn)單:gofmt 的輸出就是官方認(rèn)可的格式;
類型在變量名的后面,像這樣 var a int,來(lái)代替 C 中的 int a;
任何地方都是 UTF-8 的,包括字符串以及程序代碼。你可以在代碼中使用 Φ = Φ + 1;
Go 的許可證是完全開(kāi)源的,參閱 Go 發(fā)布的源碼中的 LICENSE 文件;
用 Go 寫(xiě)程序會(huì)非常開(kāi)心!
Erlang[4] 與 Go 在部分功能上類似。Erlang 和 Go 之間主要的區(qū)別是 Erlang 是函數(shù)式語(yǔ)言,而 Go 是命令式的。Erlang 運(yùn)行在虛擬機(jī)上,而 Go 是編譯的。Go 用起來(lái)感覺(jué)更接近 Unix。
在 Go 指南中,用一個(gè)傳統(tǒng)的方式展現(xiàn)了 Go:讓它打印 “Hello World”(Ken Thompson 和 Dennis Ritchie 在 20 世紀(jì) 70 年代,發(fā)布 C 語(yǔ)言的時(shí)候開(kāi)創(chuàng)了這個(gè)先河)。我們不認(rèn)為其他方法可以做得更好,所以就是這個(gè)吧:Go 的 “Hello World”。
http://wiki.jikexueyuan.com/project/learn-go-language/images/1.png" alt="pic" />
逐行閱讀這個(gè)程序。
0 .首行這個(gè)是必須的。所有的 Go 文件以 package
這是說(shuō)需要將 fmt 包加入 main。不是 main 的其他包都被稱為庫(kù),其他許多編程語(yǔ)言有著類似的概念(參閱第3 章)。末尾以 // 開(kāi)頭的內(nèi)容是注釋;
這同樣是注釋,不過(guò)這是被包裹于 / 和 / 之間的;
package main 必須首先出現(xiàn),緊跟著是 import。在 Go 中,package 總是首先出現(xiàn),然后是 import,然后是其他所有內(nèi)容。當(dāng) Go 程序在執(zhí)行的時(shí)候,首先調(diào)用的函數(shù)是 main.main(),這是從 C 中繼承而來(lái)。這里定義了這個(gè)函數(shù);
構(gòu)建 Go 程序的最佳途徑是使用go 工具。
構(gòu)建 helloworld 只需要:
% go build helloworld.go
結(jié)果是叫做 helloworld 的可執(zhí)行文件。
% ./helloworld
Hello, world; or ? ó?; or こんにちは世界
Go 被安裝在 ?/go,而 $GOROOT 被設(shè)置為 GOROOT=?/go;
在接下來(lái)的章節(jié)中,我們將會(huì)了解這個(gè)新語(yǔ)言的變量、基本類型、關(guān)鍵字和控制流。Go 在語(yǔ)法上有著類 C 的感覺(jué)。如果你希望將兩個(gè)(或更多)語(yǔ)句放在一行書(shū)寫(xiě),它們必須用分號(hào) (’;’) 分隔。一般情況下,你不需要分號(hào)。
Go 同其他語(yǔ)言不同的地方在于變量的類型在變量名的后面。不是:int a,而是a int。當(dāng)定義了一個(gè)變量,它默認(rèn)賦值為其類型的 null 值。這意味著,在 var a int 后,a 的值為 0。而 var s string,意味著 s 被賦值為零長(zhǎng)度字符串,也就是 ""。
在 Go 中,聲明和賦值是兩過(guò)程,但是可以連在一起。比較下面作用相同的代碼片段。
http://wiki.jikexueyuan.com/project/learn-go-language/images/2.png" alt="pic" />
在左邊使用了關(guān)鍵字 var 聲明變量,然后賦值給它。右邊的代碼使用了 := 使得在一步內(nèi)完成了聲明和賦值(這一形式只可用在函數(shù)內(nèi))。在這種情況下,變量的類型是由值推演出來(lái)的。值 15 表示是 int 類型,值 false 告訴 Go 它的類型應(yīng)當(dāng)是 bool。多個(gè) var 聲明可以成組;const 和 import 同樣允許這么做。留意圓括號(hào)的使用:
http://wiki.jikexueyuan.com/project/learn-go-language/images/3.png" alt="pic" />
有相同類型的多個(gè)變量同樣可以在一行內(nèi)完成聲明:var x, y int 讓 x 和 y 都是 int 類型變量。同樣可以使用平行賦值:
a, b := 20, 16
讓 a 和 b 都是整數(shù)變量,并且賦值 20 給 a,16 給 b。 一個(gè)特殊的變量名是 _(下劃線)。任何賦給它的值都被丟棄。在這個(gè)例子中,將 35 賦值給 b,同時(shí)丟棄 34。
_, b := 34, 35
Go 的編譯器對(duì)聲明卻未使用的變量在報(bào)錯(cuò)。下面的代碼會(huì)產(chǎn)生這個(gè)錯(cuò)誤:聲明了 i 卻未使用
http://wiki.jikexueyuan.com/project/learn-go-language/images/4.png" alt="pic" />
布爾類型表示由預(yù)定義的常量 true 和 false 代表的布爾判定值。布爾類型是 bool。
Go 有眾所周知的類型如 int,這個(gè)類型根據(jù)你的硬件決定適當(dāng)?shù)拈L(zhǎng)度。意味著在 32 位硬件上,是 32 位的;在 64 位硬件上是 64 位的。注意:int 是 32 或 64 位之一,不會(huì)定義成其他值。uint 情況相同。
如果你希望明確其長(zhǎng)度,你可以使用 int32 或者 uint32。完整的整數(shù)類型列表(符號(hào)和無(wú)符號(hào))是 int8,int16,int32,int64 和 byte,uint8,uint16,uint32,uint64。byte 是 uint8 的別名。浮點(diǎn)類型的值有 float32 和 float64 (沒(méi)有 float 類型)。64 位的整數(shù)和浮點(diǎn)數(shù)總是 64 位的,即便是在 32 位的架構(gòu)上。需要留意的是這些類型全部都是獨(dú)立的,并且混合用這些類型向變量賦值會(huì)引起編譯器錯(cuò)誤,例如下面的代碼:
http://wiki.jikexueyuan.com/project/learn-go-language/images/5.png" alt="pic" />
在行 7 觸發(fā)一個(gè)賦值錯(cuò)誤:
types.go:7: cannot use a + a (type int) as type int32 in assignment
賦值可以用八進(jìn)制、十六進(jìn)制或科學(xué)計(jì)數(shù)法:077,0xFF,1e3 或者 6.022e23 這些都是合法的。
常量在 Go 中,也就是 constant。它們?cè)诰幾g時(shí)被創(chuàng)建,只能是數(shù)字、字符串或布爾值;const x = 42 生成 x 這個(gè)常量??梢允褂?iota c 生成枚舉值。
http://wiki.jikexueyuan.com/project/learn-go-language/images/6.png" alt="pic" />
第一個(gè) iota 表示為 0,因此 a 等于 0,當(dāng) iota 再次在新的一行使用時(shí),它的值增加了 1,因此 b 的值是 1。
也可以像下面這樣,省略 Go 重復(fù)的 = iota:
http://wiki.jikexueyuan.com/project/learn-go-language/images/7.png" alt="pic" />
如果需要,可以明確指定常量的類型:
http://wiki.jikexueyuan.com/project/learn-go-language/images/8.png" alt="pic" />
另一個(gè)重要的內(nèi)建類型是 string。賦值字符串的例子:
s := "Hello World ! "
字符串在 Go 中是 UTF-8 的由雙引號(hào)(”)包裹的字符序列。如果你使用單引號(hào)(’)則表示一個(gè)字符(UTF-8 編碼)——這種在 Go 中不是 string。
一旦給變量賦值,字符串就不能修改了:在 Go 中字符串是不可變的。從 C 來(lái)的用戶,下面的情況在 Go 中是非法的。
http://wiki.jikexueyuan.com/project/learn-go-language/images/9.png" alt="pic" />
在 Go 中實(shí)現(xiàn)這個(gè),需要下面的方法:
http://wiki.jikexueyuan.com/project/learn-go-language/images/10.png" alt="pic" />
0 .轉(zhuǎn)換 s 為 rune 數(shù)組,查閱在第 4 章“轉(zhuǎn)換” 節(jié)、 59 頁(yè)的內(nèi)容;
基于分號(hào)的置入(查閱文檔 [8] 的“分號(hào)” 章節(jié)), 你需要小心使用多行字符串。如果這樣寫(xiě):
http://wiki.jikexueyuan.com/project/learn-go-language/images/11.png" alt="pic" />
會(huì)被轉(zhuǎn)換為:
http://wiki.jikexueyuan.com/project/learn-go-language/images/12.png" alt="pic" />
這是錯(cuò)誤的語(yǔ)法,應(yīng)當(dāng)這樣寫(xiě):
http://wiki.jikexueyuan.com/project/learn-go-language/images/13.png" alt="pic" />
Go 就不會(huì)在錯(cuò)誤的地方插入分號(hào)。另一種方式是使用反引號(hào) ` 作為原始字符串符號(hào):
http://wiki.jikexueyuan.com/project/learn-go-language/images/14.png" alt="pic" />
留意最后一個(gè)例子 s 現(xiàn)在也包含換行。不像轉(zhuǎn)義字符串標(biāo)識(shí),原始字符串標(biāo)識(shí)的值在引號(hào)內(nèi)的字符是不轉(zhuǎn)義的。
Rune 是 int32 的別名。用 UTF-8 進(jìn)行編碼。這個(gè)類型在什么時(shí)候使用呢?例如需要遍歷字符串中的字符。可以循環(huán)每個(gè)字節(jié)(僅在使用 US ASCII 編碼字符串時(shí)與字符等價(jià),而它們?cè)?Go 中不存在?。?。因此為了獲得實(shí)際的字符,需要使用 rune 類型。
Go 原生支持復(fù)數(shù)。它的變量類型是 complex128 (64 位虛數(shù)部分)。如果需要小一些的,還有 complex64 – 32 位的虛數(shù)部分。復(fù)數(shù)寫(xiě)為 re + imi,re 是實(shí)數(shù)部分,im 是虛數(shù)部分,而 i 是標(biāo)記 ’i’ (p