本書(shū)由《C程序設(shè)計(jì)語(yǔ)言》的作者Kernighan和谷歌公司Go團(tuán)隊(duì)主管AlanDonovan聯(lián)袂撰寫(xiě),是學(xué)習(xí)Go語(yǔ)言程序設(shè)計(jì)指南。本書(shū)共13章,主要內(nèi)容包括:Go的基礎(chǔ)知識(shí)、基本結(jié)構(gòu)、基本數(shù)據(jù)類(lèi)型、復(fù)合數(shù)據(jù)類(lèi)型、函數(shù)、方法、接口、goroutine、通道、共享變量的并發(fā)性、包、go工具、測(cè)試、反射等。本書(shū)適合作為計(jì)算機(jī)相關(guān)專(zhuān)業(yè)的教材,也可供Go語(yǔ)言愛(ài)好者閱讀。
The Go Programming Language“Go是一種開(kāi)源的程序設(shè)計(jì)語(yǔ)言,它意在使得人們能夠方便地構(gòu)建簡(jiǎn)單、可靠、高效的軟件!保▉(lái)自Go官網(wǎng)golang.org)Go在2007年9月形成構(gòu)想,并于2009年11月發(fā)布,其發(fā)明人是Robert Griesemer、Rob Pike和Ken Thompson,這幾位都任職于Google。該語(yǔ)言及其配套工具集使得編譯和執(zhí)行既富有表達(dá)力又高效,而且使得程序員能夠輕松寫(xiě)出可靠、健壯的程序。
Go和C從表面上看起來(lái)相似,而且和C一樣,它也是專(zhuān)業(yè)程序員使用的一種工具,兼有事半功倍之效。但是Go遠(yuǎn)不止是C的一種升級(jí)版本。基于多種其他語(yǔ)言,它取其精華,去其糟粕。它實(shí)現(xiàn)并發(fā)功能的設(shè)施是全新的、高效的,實(shí)現(xiàn)數(shù)據(jù)抽象和面向?qū)ο蟮耐緩绞菢O其靈活的。它還實(shí)現(xiàn)了自動(dòng)化的內(nèi)存管理,或稱(chēng)為垃圾回收。
Go特別適用于構(gòu)建基礎(chǔ)設(shè)施類(lèi)軟件(如網(wǎng)絡(luò)服務(wù)器),以及程序員使用的工具和系統(tǒng)等。但它的的確確是一種通用語(yǔ)言,而且在諸多領(lǐng)域(如圖像處理、移動(dòng)應(yīng)用和機(jī)器學(xué)習(xí))中都能發(fā)現(xiàn)它的身影。它在很多場(chǎng)合下用于替換無(wú)類(lèi)型的腳本語(yǔ)言,這是由于它兼顧了表達(dá)力和安全性:Go程序通常比動(dòng)態(tài)語(yǔ)言程序運(yùn)行速度要快,由于意料之外的類(lèi)型錯(cuò)誤而導(dǎo)致崩潰的情形更是少得多。
Go是個(gè)開(kāi)源項(xiàng)目,所以其編譯器、庫(kù)和工具的源代碼是人人皆可免費(fèi)取得的。來(lái)自全世界的社區(qū)都在積極地向這個(gè)項(xiàng)目貢獻(xiàn)代碼。Go的運(yùn)行環(huán)境包括類(lèi)UNIX系統(tǒng)——Linux、FreeBSD、OpenBSD和Mac OS X,還有Plan 9和Microsoft Windows。只要在其中一個(gè)環(huán)境中寫(xiě)了一個(gè)程序,那么基本上不加修改它就可以運(yùn)行在其他環(huán)境中。
本書(shū)旨在幫助讀者立刻開(kāi)始使用Go,以及熟練掌握這門(mén)語(yǔ)言,并充分地利用Go的語(yǔ)言特性和標(biāo)準(zhǔn)庫(kù)來(lái)撰寫(xiě)清晰的、符合習(xí)慣用法的、高效的程序。
Go的起源和生物學(xué)物種一樣,成功的語(yǔ)言會(huì)繁衍后代,這些后代語(yǔ)言會(huì)從它們的祖先那里汲取各種優(yōu)點(diǎn);有時(shí)候,語(yǔ)言間的“混血”會(huì)產(chǎn)生異常強(qiáng)大的力量;在一些罕見(jiàn)情況下,某個(gè)重大的語(yǔ)言特性也可能憑空出現(xiàn)而并無(wú)先例。通過(guò)考察語(yǔ)言間的影響,我們可以學(xué)得不少知識(shí),比如語(yǔ)言為什么會(huì)變成這個(gè)樣子,以及它適合用于哪些環(huán)境,等等。
下圖展示了更早出現(xiàn)的程序設(shè)計(jì)語(yǔ)言對(duì)Go產(chǎn)生的最重要影響。
Go有時(shí)會(huì)稱(chēng)為“類(lèi)C語(yǔ)言”或“21世紀(jì)的C”。從C中,Go繼承了表達(dá)式語(yǔ)法、控制流語(yǔ)句、基本數(shù)據(jù)類(lèi)型、按值調(diào)用的形參傳遞和指針,但比這些更重要的是,繼承了C所強(qiáng)調(diào)的要點(diǎn):程序要編譯成高效的機(jī)器碼,并自然地與所處的操作系統(tǒng)提供的抽象機(jī)制相配合。
可是,Go的家譜中還有其他祖先。產(chǎn)生主要影響的是由Niklaus Wirth設(shè)計(jì)的、以Pascal為發(fā)端的一個(gè)語(yǔ)言支流。Modula-2啟發(fā)了包概念。Oberon消除了模塊接口文件和模塊實(shí)現(xiàn)文件之間的差異。Oberon-2影響了包、導(dǎo)入和聲明的語(yǔ)法,并提供了方法聲明的語(yǔ)法。
Go的另一支世系祖先——它使得Go相對(duì)于當(dāng)下的程序設(shè)計(jì)語(yǔ)言顯得卓然不群,是在貝爾實(shí)驗(yàn)室開(kāi)發(fā)的一系列名不見(jiàn)經(jīng)傳的研究用語(yǔ)言。這些語(yǔ)言都受到了通信順序進(jìn)程(Communicating Sequential Process,CSP)的啟發(fā),CSP由Tony Hoare于1978年在發(fā)表的關(guān)于并發(fā)性基礎(chǔ)的開(kāi)創(chuàng)性論文中提出。在CSP中,程序就是一組無(wú)共享狀態(tài)進(jìn)程的并行組合,進(jìn)程間的通信和同步采用通道完成。不過(guò),Hoare提出的CSP是一種形式語(yǔ)言,僅用于描述并發(fā)性的基本概念,并不是一種用來(lái)撰寫(xiě)可執(zhí)行程序的程序設(shè)計(jì)語(yǔ)言。
Rob Pike等人開(kāi)始動(dòng)手做一些實(shí)驗(yàn),嘗試把CSP實(shí)現(xiàn)為真正的語(yǔ)言。第一種這樣的語(yǔ)言稱(chēng)為Squeak(“和鼠類(lèi)溝通的語(yǔ)言”),它是一種用于處理鼠標(biāo)和鍵盤(pán)事件的語(yǔ)言,其中具有靜態(tài)創(chuàng)建的通道。緊接著它的是Newsqueak,它具有類(lèi)C的語(yǔ)句和表達(dá)式語(yǔ)法,以及類(lèi)Pascal的類(lèi)型記法。它是一種純粹的函數(shù)式語(yǔ)言,具有垃圾回收功能,同樣也以管理鍵盤(pán)、鼠標(biāo)和窗口事件為目標(biāo)。通道變成了“一等”值(first-class value),它可以動(dòng)態(tài)創(chuàng)建并用變量存儲(chǔ)。
Plan 9操作系統(tǒng)將這些思想都納入一種稱(chēng)為Alef的語(yǔ)言中。Alef嘗試將Newsqueak改造成一種可用的系統(tǒng)級(jí)程序設(shè)計(jì)語(yǔ)言,但垃圾回收功能的缺失使得它在處理并發(fā)性時(shí)捉襟見(jiàn)肘。
Go中的其他結(jié)構(gòu)也會(huì)不時(shí)顯示出某些并非來(lái)自祖先的基因。例如,iota多多少少有點(diǎn)APL的影子,而嵌套函數(shù)的詞法作用域則來(lái)自Scheme(以及由之而來(lái)的大部分語(yǔ)言)。在Go語(yǔ)言中,也可以發(fā)現(xiàn)全新的變異。Go中新穎的slice不僅為動(dòng)態(tài)數(shù)組提供了高效的隨機(jī)訪問(wèn)功能,還允許舊式鏈表的復(fù)雜共享機(jī)制。另外,defer語(yǔ)句也是Go中新引入的。
Go項(xiàng)目所有的程序設(shè)計(jì)語(yǔ)言都反映了其發(fā)明者的程序設(shè)計(jì)哲理,其中相當(dāng)大的一部分是對(duì)于此前語(yǔ)言已知缺點(diǎn)的應(yīng)對(duì)措施。Go這個(gè)項(xiàng)目也誕生于挫敗感,這種挫敗感來(lái)源于Google的若干復(fù)雜性激增的軟件系統(tǒng)。(而且這個(gè)問(wèn)題絕非Google所獨(dú)有的。)“復(fù)雜性是以乘積方式增長(zhǎng)的!盧ob Pike如是說(shuō)。為了修復(fù)某個(gè)問(wèn)題,一點(diǎn)點(diǎn)地將系統(tǒng)的某個(gè)部分變得更加復(fù)雜,這不可避免地也給其他部分增加了復(fù)雜性。在不斷要求增加系統(tǒng)功能、選項(xiàng)和配置,以及快速發(fā)布的壓力之下,簡(jiǎn)單性往往被忽視了(盡管長(zhǎng)期來(lái)看,簡(jiǎn)單性才是好軟件的不二法門(mén))。
目 錄
The Go Programming Language
出版者的話(huà)
譯者序
前言
第1章 入門(mén) 1
1.1 hello,world 1
1.2 命令行參數(shù) 3
1.3 找出重復(fù)行 6
1.4 GIF動(dòng)畫(huà) 10
1.5 獲取一個(gè)URL 12
1.6 并發(fā)獲取多個(gè)URL 13
1.7 一個(gè)Web服務(wù)器 14
1.8 其他內(nèi)容 17
第2章 程序結(jié)構(gòu) 20
2.1 名稱(chēng) 20
2.2 聲明 21
2.3 變量 22
2.3.1 短變量聲明 22
2.3.2 指針 23
2.3.3 new函數(shù) 25
2.3.4 變量的生命周期 26
2.4 賦值 27
2.4.1 多重賦值 27
2.4.2 可賦值性 28
2.5 類(lèi)型聲明 29
2.6 包和文件 30
2.6.1 導(dǎo)入 31
2.6.2 包初始化 33
2.7 作用域 34
第3章 基本數(shù)據(jù) 38
3.1 整數(shù) 38
3.2 浮點(diǎn)數(shù) 42
3.3 復(fù)數(shù) 45
3.4 布爾值 47
3.5 字符串 47
3.5.1 字符串字面量 49
3.5.2 Unicode 49
3.5.3 UTF-8 50
3.5.4 字符串和字節(jié)slice 53
3.5.5 字符串和數(shù)字的相互轉(zhuǎn)換 56
3.6 常量 56
3.6.1 常量生成器iota 57
3.6.2 無(wú)類(lèi)型常量 59
第4章 復(fù)合數(shù)據(jù)類(lèi)型 61
4.1 數(shù)組 61
4.2 slice 63
4.2.1 append函數(shù) 66
4.2.2 slice就地修改 69
4.3 map 71
4.4 結(jié)構(gòu)體 76
4.4.1 結(jié)構(gòu)體字面量 78
4.4.2 結(jié)構(gòu)體比較 80
4.4.3 結(jié)構(gòu)體嵌套和匿名成員 80
4.5 JSON 82
4.6 文本和HTML模板 87
第5章 函數(shù) 92
5.1 函數(shù)聲明 92
5.2 遞歸 93
5.3 多返回值 96
5.4 錯(cuò)誤 98
5.4.1 錯(cuò)誤處理策略 99
5.4.2 文件結(jié)束標(biāo)識(shí) 101
5.5 函數(shù)變量 102
5.6 匿名函數(shù) 104
5.7 變長(zhǎng)函數(shù) 110
5.8 延遲函數(shù)調(diào)用 111
5.9 宕機(jī) 115
5.10 恢復(fù) 118
第6章 方法 120
6.1 方法聲明 120
6.2 指針接收者的方法 122
6.3 通過(guò)結(jié)構(gòu)體內(nèi)嵌組成類(lèi)型 124
6.4 方法變量與表達(dá)式 127
6.5 示例:位向量 128
6.6 封裝 130
第7章 接口 133
7.1 接口即約定 133
7.2 接口類(lèi)型 135
7.3 實(shí)現(xiàn)接口 136
7.4 使用flag.Value來(lái)解析參數(shù) 139
7.5 接口值 141
7.6 使用sort.Interface來(lái)排序 144
7.7 http.Handler接口 148
7.8 error接口 152
7.9 示例:表達(dá)式求值器 154
7.10 類(lèi)型斷言 160
7.11 使用類(lèi)型斷言來(lái)識(shí)別錯(cuò)誤 161
7.12 通過(guò)接口類(lèi)型斷言來(lái)查詢(xún)特性 162
7.13 類(lèi)型分支 164
7.14 示例:基于標(biāo)記的XML解析 166
7.15 一些建議 168
第8章 goroutine和通道 170
8.1 goroutine 170
8.2 示例:并發(fā)時(shí)鐘服務(wù)器 171
8.3 示例:并發(fā)回聲服務(wù)器 174
8.4 通道 176
8.4.1 無(wú)緩沖通道 177
8.4.2 管道 178
8.4.3 單向通道類(lèi)型 180
8.4.4 緩沖通道 181
8.5 并行循環(huán) 183
8.6 示例:并發(fā)的Web爬蟲(chóng) 187
8.7 使用select多路復(fù)用 190
8.8 示例:并發(fā)目錄遍歷 192
8.9 取消 195
8.10 示例:聊天服務(wù)器 198
第9章 使用共享變量實(shí)現(xiàn)并發(fā) 201
9.1 競(jìng)態(tài) 201
9.2 互斥鎖:sync.Mutex 205
9.3 讀寫(xiě)互斥鎖:sync.RWMutex 208
9.4 內(nèi)存同步 208
9.5 延遲初始化:sync.Once 210
9.6 競(jìng)態(tài)檢測(cè)器 212
9.7 示例:并發(fā)非阻塞緩存 212
9.8 goroutine與線程 218
9.8.1 可增長(zhǎng)的棧 219
9.8.2 goroutine調(diào)度 219
9.8.3 GOMAXPROCS 219
9.8.4 goroutine沒(méi)有標(biāo)識(shí) 220
第10章 包和go工具 221
10.1 引言 221
10.2 導(dǎo)入路徑 221
10.3 包的聲明 222
10.4 導(dǎo)入聲明 223
10.5 空導(dǎo)入 223
10.6 包及其命名 225
10.7 go工具 226
10.7.1 工作空間的組織 227
10.7.2 包的下載 228
10.7.3 包的構(gòu)建 229
10.7.4 包的文檔化 231
10.7.5 內(nèi)部包 232
10.7.6 包的查詢(xún) 233
第11章 測(cè)試 235
11.1 go test工具 235
11.2 Test函數(shù) 236
11.2.1 隨機(jī)測(cè)試 239
11.2.2 測(cè)試命令 240
11.2.3 白盒測(cè)試 242
11.2.4 外部測(cè)試包 245
11.2.5 編寫(xiě)有效測(cè)試 246
11.2.6 避免脆弱的測(cè)試 247
11.3 覆蓋率 248
11.4 Benchmark函數(shù) 250
11.5 性能剖析 252
11.6 Example函數(shù) 254
第12章 反射 256
12.1 為什么使用反射 256
12.2 reflect.Type和reflect.Value 257
12.3 Display:一個(gè)遞歸的值顯示器 259
12.4 示例:編碼S表達(dá)式 263
12.5 使用reflect.Value來(lái)設(shè)置值 266
12.6 示例:解碼S表達(dá)式 268
12.7 訪問(wèn)結(jié)構(gòu)體字段標(biāo)簽 271
12.8 顯示類(lèi)型的方法 273
12.9 注意事項(xiàng) 274
第13章 低級(jí)編程 276
13.1 unsafe.Sizeof、Alignof 和Offsetof 276
13.2 unsafe.Pointer 278
13.3 示例:深度相等 280
13.4 使用cgo調(diào)用C代碼 282
13.5 關(guān)于安全的注意事項(xiàng) 286