《深入理解Go語言(第3版)》詳細闡述了Go語言開發(fā)的基本解決方案,主要包括Go語言快速入門、基本數(shù)據(jù)類型、復(fù)合數(shù)據(jù)類型、反射和接口、Go包和函數(shù)、告訴UNIX系統(tǒng)該做什么、Go語言中的并發(fā)性、構(gòu)建Web服務(wù)、TCP/IP和WebSocket、REST APIs、代碼測試與性能分析、與gRPC協(xié)同工作、Go語言中的泛型等內(nèi)容。此外,本書還提供了相應(yīng)的示例、代碼,以幫助讀者進一步理解相關(guān)方案的實現(xiàn)過程。
《深入理解Go語言(第3版)》全面介紹了Go語言開發(fā)的核心內(nèi)容,從基礎(chǔ)到高級特性如并發(fā)、泛型及gRPC應(yīng)用,并結(jié)合實例講解,是掌握Go語言編程的理想選擇。
本版包含了許多激動人心的新主題,如編寫 RESTful 服務(wù)、使用 WebSocket 協(xié)議,以及利用 GitHub Actions 和 GitLab Actions 進行 Go 項目的開發(fā),還有泛型內(nèi)容和許多實用工具的開發(fā)。此外,我努力使本版比第 2 版更加精簡,并以更自然的結(jié)構(gòu)安排內(nèi)容,使其閱讀起來更加輕松快捷,特別適合那些忙碌的專業(yè)人士。
我也努力在書中融入了適量的理論知識和實踐內(nèi)容但只有您,親愛的讀者,才能評判我是否成功。請務(wù)必嘗試每章末尾的練習(xí),并在有任何建議或想法時,及時與我聯(lián)系。
適用讀者
本書是為那些希望將 Go 語言知識提升到更高水平的中級 Go 程序員準備的。對于那些希望學(xué)習(xí) Go 語言,同時不想重復(fù)學(xué)習(xí)編程基礎(chǔ)的經(jīng)驗豐富的其他編程語言開發(fā)者來說,本書也會非常有用。
本書內(nèi)容
第 1 章首先討論了 Go 語言的歷史、Go 的重要特性及 Go 的優(yōu)勢。接著介紹了 godoc 實用程序和 go doc 工具,并解釋了如何編譯和執(zhí)行 Go 程序。之后,討論了打印輸出和獲取用戶輸入、處理命令行參數(shù)及使用日志文件。最后,開發(fā)了一個基本的電話簿應(yīng)用程序版本,并將在接下來的章節(jié)中不斷改進它。
第 2 章討論了 Go 語言的基礎(chǔ)數(shù)據(jù)類型,包括數(shù)值型和非數(shù)值型,以及將相似數(shù)據(jù)類型的數(shù)據(jù)分組的數(shù)組和切片。本章還涉及了 Go 語言的指針、常量及處理日期和時間。最后是關(guān)于生成隨機數(shù),以及使用隨機數(shù)據(jù)更新電話簿應(yīng)用程序。
第 3 章從映射(maps)開始,然后深入結(jié)構(gòu)體和結(jié)構(gòu)體關(guān)鍵字(struct)。此外,還討論了正則表達式、模式匹配及處理 CSV 文件。最后,通過為電話簿應(yīng)用程序添加數(shù)據(jù)持久性來改進它。
第 4 章講述了反射、接口以及類型方法,這些是附加到數(shù)據(jù)類型上的功能。本章還包括使用 sort.Interface 接口對切片進行排序、空接口的使用、類型斷言、類型開關(guān)及錯誤數(shù)據(jù)類型。此外,討論了 Go 如何模擬一些面向?qū)ο蟮母拍睿缓髮﹄娫挷緫?yīng)用程序進行了改進。
第 5 章全面介紹了包、模塊以及作為包主要元素的函數(shù)。在本章中,創(chuàng)建了一個用于與 PostgreSQL 數(shù)據(jù)庫交互的 Go 包,為其編寫了文檔,并解釋了有時難以掌握的 defer 關(guān)鍵字的使用。此外還包含了關(guān)于使用 GitLab Runners 和 GitHub Actions 進行自動化的信息,以及如何為 Go 二進制文件創(chuàng)建 Docker 鏡像。
第 6 章是關(guān)于系統(tǒng)編程的,包括處理命令行參數(shù)、處理 UNIX 信號、文件輸入輸出、io.Reader 和 io.Writer 接口,以及使用 viper 和 cobra 包等主題。此外,討論了處理 JSON、XML 和 YAML 文件,創(chuàng)建了一個方便的命令行工具用于發(fā)現(xiàn) UNIX 文件系統(tǒng)中的循環(huán),并討論了在 Go 二進制文件中嵌入文件,以及 os.ReadDir()函數(shù)、os.DirEntry 類型和 io/fs 包的使用。最后,更新了電話簿應(yīng)用程序以使用 JSON 數(shù)據(jù),并在 cobra 包的幫助下將其轉(zhuǎn)換為一個合適的命令行工具。
第 7 章討論了 goroutines、channels 和 pipelines。介紹了進程、線程和 goroutines 之間的區(qū)別,sync 包,以及 Go 調(diào)度器的運作方式。此外,探索了 select 關(guān)鍵字的使用,討論了 Go channels 的各種類型,以及共享內(nèi)存、互斥鎖、sync.Mutex 類型和 sync.RWMutex 類型。最后其余部分討論了 context 包、semaphore 包、工作池、如何對 goroutines 設(shè)置超時,以及如何檢測競態(tài)條件。
第 8 章討論了 net/http 包,Web 服務(wù)器和 Web 服務(wù)的開發(fā),將指標(biāo)暴露給 Prometheus,在 Grafana 中可視化指標(biāo),開發(fā) Web 客戶端和創(chuàng)建文件服務(wù)器。最后還把電話簿應(yīng)用程序轉(zhuǎn)換為 Web 服務(wù),并為其創(chuàng)建了一個命令行客戶端。
第 9 章涉及 net 包、TCP/IP,以及 TCP 和 UDP 協(xié)議,還有 UNIX 域套接字和 WebSocket 協(xié)議。最后開發(fā)了許多網(wǎng)絡(luò)服務(wù)器和客戶端。
第 10 章全面介紹了 REST API 和 RESTful 服務(wù)的使用。學(xué)習(xí)如何定義 REST API,開發(fā)強大的并發(fā) RESTful 服務(wù)器,以及作為 RESTful 服務(wù)客戶端的命令行工具。最后介紹了 Swagger 用于創(chuàng)建 REST API 文檔,并學(xué)習(xí)了如何上傳和下載二進制文件。
第 11 章討論了代碼測試、代碼優(yōu)化和代碼性能分析,交叉編譯、基準測試 Go 代碼、創(chuàng)建示例函數(shù)、使用 go:generate,以及尋找不可達的 Go 代碼。
第 12 章全面介紹了在 Go 中使用 gRPC。gRPC 是由 Google 開發(fā)的 RESTful 服務(wù)的替代品。同時闡述了如何定義 gRPC 服務(wù)的方法和消息,如何將它們轉(zhuǎn)換為 Go 代碼,以及如何為該 gRPC 服務(wù)開發(fā)服務(wù)器和客戶端。
第 13 章是關(guān)于泛型,以及如何使用新語法編寫泛型函數(shù)和定義泛型數(shù)據(jù)類型。
附錄講述了 Go 垃圾收集器的運作,并闡述了這個 Go 組件如何影響代碼性能。
如何利用本書
本書需要一臺安裝了相對較新版本的 UNIX 計算機,這包括任何運行 macOS X、macOS 或 Linux 的機器。大部分展示的代碼在不作任何修改的情況下也可以在 Microsoft Windows 機器上運行。
為了最大限度地利用本書,您應(yīng)該盡快嘗試將每一章的知識應(yīng)用到自己的程序中,并看看哪些有效,哪些無效。正如我之前告訴您的,嘗試解決每章末尾的練習(xí)題,或者創(chuàng)建您自己的編程問題。
Mihalis Tsoukalos是一位頗有成就的作家,同時也是Unix管理員、程序員、DBA和數(shù)學(xué)家,他喜歡寫技術(shù)文章和學(xué)習(xí)新技術(shù)。他的研究興趣包括編程語言、數(shù)據(jù)庫和操作系統(tǒng)。他擁有佩特拉斯大學(xué)的數(shù)學(xué)學(xué)士學(xué)位和英國倫敦大學(xué)學(xué)院的信息技術(shù)碩士學(xué)位。他曾為Sys Admin、MacTech、C/ c 用戶期刊、Linux期刊、Linux用戶與開發(fā)者、Linux Format、Linux Voice等撰寫各類技術(shù)文章。
第 1 章 Go 語言快速入門 1
1.1 Go 語言簡介 1
1.1.1 Go 語言的歷史 2
1.1.2 為什么選擇 UNIX 而不是 Windows 3
1.1.3 Go 語言的優(yōu)缺點 4
1.1.4 go doc 和 godoc 實用程序 5
1.2 Hello World! 6
1.2.1 函數(shù)簡介 7
1.2.2 包簡介 7
1.3 運行 Go 代碼 8
1.3.1 編譯 Go 代碼 8
1.3.2 像腳本語言那樣使用 Go 語言 8
1.3.3 導(dǎo)入格式和編碼規(guī)則 9
1.4 Go 語言的重要特性 10
1.4.1 定義和使用變量 10
1.4.2 控制程序流 13
1.4.3 使用 for 循環(huán)和 range 進行迭代 15
1.4.4 獲取用戶輸入 17
1.4.5 使用 error 變量區(qū)分輸入類型 21
1.4.6 理解 Go 語言的并發(fā)模型 23
1.5 開發(fā) Go 語言中的 which(1)工具 25
1.6 記錄信息 27
1.6.1 log.Fatal()和 log.Panic() 29
1.6.2 寫入自定義日志文件 30
1.6.3 在日志條目中打印行號 32
1.7 Go 語言中的泛型 33
1.8 開發(fā)一個基本的電話簿應(yīng)用程序 35
1.9 本章練習(xí) 38
1.10 本章小結(jié) 39
1.11 附加資源 39
第 2 章 基本數(shù)據(jù)類型 40
2.1 error 數(shù)據(jù)類型 40
2.2 數(shù)值數(shù)據(jù)類型 43
2.3 非數(shù)值數(shù)據(jù)類型 46
2.3.1 字符串、字符和 rune 46
2.3.2 日期和時間 53
2.4 Go 常量 58
2.5 將相似數(shù)據(jù)分組 61
2.5.1 數(shù)組 61
2.5.2 切片 61
2.6 指針 79
2.7 生成隨機數(shù) 82
2.7.1 生成隨機字符串 83
2.7.2 生成安全的隨機數(shù) 85
2.8 更新電話簿應(yīng)用程序 85
2.9 本章練習(xí) 87
2.10 本章小結(jié) 87
2.11 附加資源 87
第 3 章 復(fù)合數(shù)據(jù)類型 88
3.1 映射 88
3.1.1 存儲到一個 nil 映射 89
3.1.2 迭代映射 91
3.2 結(jié)構(gòu)體 92
3.2.1 定義新的結(jié)構(gòu)體 92
3.2.2 使用 new 關(guān)鍵字 93
3.2.3 結(jié)構(gòu)體切片 95
3.3 正則表達式和模式匹配 97
3.3.1 Go 語言中的正則表達式 97
3.3.2 匹配姓名和姓氏 98
3.3.3 匹配整數(shù) 99
3.3.4 匹配記錄中的字段 100
3.4 改進電話簿應(yīng)用程序 101
3.4.1 處理 CSV 文件 101
3.4.2 添加索引 105
3.4.3 電話簿應(yīng)用程序的改進版本 106
3.5 本章練習(xí) 114
3.6 本章小結(jié) 114
3.7 附加資源 114
第 4 章 反射和接口 115
4.1 反射 115
4.1.1 Go 結(jié)構(gòu)體的內(nèi)部結(jié)構(gòu) 117
4.1.2 使用反射修改結(jié)構(gòu)體值 119
4.1.3 反射的 3 個缺點 120
4.2 類型方法 121
4.2.1 創(chuàng)建類型方法 121
4.2.2 使用類型方法 122
4.3 接口 125
4.3.1 sort.Interface 接口 127
4.3.2 空接口 130
4.3.3 類型斷言和類型開關(guān) 131
4.3.4 map[string]interface{}映射 135
4.3.5 error 數(shù)據(jù)類型 138
4.3.6 編寫自己的接口 142
4.4 處理兩種不同的 CSV 文件格式 147
4.5 Go 語言中的面向?qū)ο缶幊?151
4.6 更新電話簿應(yīng)用程序 154
4.6.1 設(shè)置 CSV 文件值 155
4.6.2 使用 sort 包 156
4.7 本章練習(xí) 158
4.8 本章小結(jié) 158
4.9 附加資源 158
第 5 章 Go 包和函數(shù) 159
5.1 Go 包 159
5.2 函數(shù) 162
5.2.1 匿名函數(shù) 163
5.2.2 返回多個值的函數(shù) 163
5.2.3 可以命名的函數(shù)返回值 164
5.2.4 接收其他函數(shù)作為參數(shù)的函數(shù) 165
5.2.5 函數(shù)可以返回其他函數(shù) 167
5.2.6 可變參數(shù)函數(shù) 168
5.2.7 defer 關(guān)鍵字 172
5.3 開發(fā)自己的包 174
5.3.1 init()函數(shù) 175
5.3.2 執(zhí)行順序 175
5.4 使用 GitHub 存儲 Go 包 176
5.5 用于操作數(shù)據(jù)庫的包 178
5.5.1 了解數(shù)據(jù)庫 179
5.5.2 存儲 Go 包 183
5.5.3 Go 包的設(shè)計 184
5.5.4 Go 包的實現(xiàn) 186
5.5.5 測試 Go 包 193
5.6 模塊 197
5.7 創(chuàng)建更好的包 197
5.8 生成文檔 198
5.9 GitLab Runners 和 Go 205
5.9.1 初始版本的配置文件 205
5.9.2 最終版本的配置文件 207
5.10 GitHub Actions 和 Go 209
5.11 版本控制工具 211
5.12 本章練習(xí) 213
5.13 本章小結(jié) 213
5.14 附加資源 213
第 6 章 告訴 UNIX 系統(tǒng)該做什么 215
6.1 stdin、stdout 和 stderr 216
6.2 UNIX 進程 216
6.3 處理 UNIX 信號 217
6.4 文件 I/O 220
6.4.1 io.Reader 和 io.Writer 接口 220
6.4.2 使用和濫用 io.Reader 和 io.Writer 221
6.4.3 緩沖和非緩沖文件 I/O 225
6.5 讀取文本文件 226
6.5.1 逐行讀取文本文件 226
6.5.2 逐字讀取文本文件 227
6.5.3 逐字符讀取文本文件 229
6.5.4 從/dev/random 讀取 230
6.5.5 從文件中讀取特定數(shù)量的數(shù)據(jù) 231
6.6 寫入文件 232
6.7 處理 JSON 數(shù)據(jù) 235
6.7.1 使用 Marshal()和 Unmarshal() 235
6.7.2 Go 結(jié)構(gòu)體和 JSON 237
6.7.3 以流的形式讀取和寫入 JSON 數(shù)據(jù) 238
6.7.4 美觀打印 JSON 記錄 239
6.8 處理 XML 數(shù)據(jù) 241
6.9 處理 YAML 數(shù)據(jù) 243
6.10 viper 包 245
6.10.1 使用命令行標(biāo)志 246
6.10.2 讀取 JSON 配置文件 248
6.11 cobra 包 252
6.11.1 基于 3 條命令的實用工具 253
6.11.2 添加命令行標(biāo)志 254
6.11.3 創(chuàng)建命令行別名 255
6.11.4 創(chuàng)建子命令 255
6.12 在 UNIX 文件系統(tǒng)中查找循環(huán) 256
6.13 Go 1.16 中的新特性 259
6.13.1 嵌入文件 259
6.13.2 ReadDir 和 DirEntry 262
6.13.3 io/fs 包 264
6.14 更新電話簿應(yīng)用程序 266
6.14.1 使用 cobra 266
6.14.2 存儲和加載 JSON 數(shù)據(jù) 267
6.14.3 實現(xiàn) delete 命令 268
6.14.4 實現(xiàn) insert 命令 269
6.14.5 實現(xiàn) list 命令 269
6.14.6 實現(xiàn) search 命令 269
6.15 本章練習(xí) 271
6.16 本章小結(jié) 271
6.17 附加資源 272
第 7 章 Go 語言中的并發(fā)性 273
7.1 進程、線程和協(xié)程 274
7.2 Go 調(diào)度器 274
7.2.1 GOMAXPROCS 環(huán)境變量 276
7.2.2 并發(fā)和并行 277
7.3 協(xié)程 278
7.3.1 創(chuàng)建一個協(xié)程 278
7.3.2 創(chuàng)建多個協(xié)程 279
7.3.3 等待協(xié)程完成 279
7.3.4 Add()和 Done()調(diào)用的次數(shù)不同 281
7.3.5 使用協(xié)程創(chuàng)建多個文件 283
7.4 通道 283
7.4.1 向通道寫入和從通道讀取 284
7.4.2 從已關(guān)閉的通道接收 287
7.4.3 作為函數(shù)參數(shù)的通道 288
7.5 競態(tài)條件 288
7.6 select 關(guān)鍵字 291
7.7 協(xié)程超時 293
7.7.1 main()中的協(xié)程超時 293
7.7.2 main()之外的協(xié)程超時 294
7.8 重新審視 Go 通道 295
7.8.1 緩沖通道 296
7.8.2 nil 通道 298
7.8.3 工作池 299
7.8.4 信號通道 303
7.9 共享內(nèi)存和共享變量 305
7.9.1 sync.Mutex 類型 306
7.9.2 sync.RWMutex 類型 308
7.9.3 atomic 包 311
7.9.4 使用協(xié)程共享內(nèi)存 312
7.10 閉包變量和 go 語句 315
7.11 context 包 317
7.12 semaphore 包 322
7.13 本章練習(xí) 325
7.14 本章小結(jié) 325
7.15 附加資源 325
第 8 章 構(gòu)建 Web 服務(wù) 326
8.1 net/http 包 326
8.1.1 http.Response 類型 326
8.1.2 http.Request 類型 327
8.1.3 http.Transport 類型 328
8.2 創(chuàng)建一個 Web 服務(wù)器 329
8.3 更新電話簿應(yīng)用程序 332
8.3.1 定義 API 332
8.3.2 實現(xiàn)處理程序 333
8.4 將指標(biāo)公開與 Prometheus 341
8.4.1 runtime/metrics 包 341
8.4.2 公開指標(biāo) 343
8.4.3 讀取指標(biāo) 351
8.4.4 將指標(biāo)放入 Prometheus 352
8.4.5 在 Grafana 中可視化 Prometheus 指標(biāo) 356
8.5 開發(fā) Web 客戶端 357
8.5.1 使用 http.NewRequest()改進客戶端 359
8.5.2 為電話薄服務(wù)創(chuàng)建客戶端 362
8.6 創(chuàng)建文件服務(wù)器 368
8.7 對 HTTP 連接進行超時設(shè)置 371
8.7.1 使用 SetDeadline() 371
8.7.2 在客戶端設(shè)置超時周期 372
8.7.3 在服務(wù)器端設(shè)置超時周期 375
8.8 本章練習(xí) 376
8.9 本章小結(jié) 377
8.10 附加資源 377
第 9 章 TCP/IP 和 WebSocket 378
9.1 TCP/IP 378
9.2 net 包 380
9.3 開發(fā) TCP 客戶端 380
9.3.1 利用 net.Dial()開發(fā) TCP 客戶端 380
9.3.2 利用 net.DialTCP()開發(fā) TCP 客戶端 382
9.4 開發(fā) TCP 服務(wù)器 384
9.4.1 利用 net.Listen()開發(fā) TCP 服務(wù)器 384
9.4.2 利用 net.ListenTCP()開發(fā) TCP 服務(wù)器 386
9.5 開發(fā) UDP 客戶端 389
9.6 開發(fā) UDP 服務(wù)器 391
9.7 開發(fā)并發(fā) TCP 服務(wù)器 394
9.8 使用 UNIX 域套接字 396
9.8.1 UNIX 域套接字服務(wù)器 396
9.8.2 UNIX 域套接字客戶端 399
9.9 創(chuàng)建 WebSocket 服務(wù)器 401
9.9.1 服務(wù)器的實現(xiàn) 402
9.9.2 使用 websocat 405
9.9.3 使用 JavaScript 406
9.10 開發(fā) WebSocket 客戶端 409
9.11 本章練習(xí) 413
9.12 本章小結(jié) 414
9.13 附加資源 414
第 10 章 REST APIs 415
10.1 REST 簡介 415
10.2 開發(fā) RESTful 服務(wù)器和客戶端 417
10.2.1 RESTful 服務(wù)器 418
10.2.2 RESTful 客戶端 426
10.3 創(chuàng)建一個功能性的 RESTful 服務(wù)器 435
10.3.1 REST API 435
10.3.2 使用 gorilla/mux 436
10.3.3 使用子路由器 437
10.3.4 與數(shù)據(jù)庫協(xié)作 437
10.3.5 測試 restdb 包 442
10.3.6 實現(xiàn) RESTful 服務(wù)器 444
10.3.7 測試 RESTful 服務(wù)器 448
10.4 開發(fā) RESTful 客戶端 451
10.4.1 創(chuàng)建命令行客戶端的結(jié)構(gòu) 452
10.4.2 實現(xiàn) RESTful 客戶端命令 453
10.4.3 創(chuàng)建 RESTful 客戶端 457
10.4.4 處理多個 REST API 版本 459
10.5 上傳和下載二進制文件 459
10.6 使用 Swagger 進行 REST API 文檔編寫 464
10.6.1 為 REST API 編寫文檔 466
10.6.2 生成文檔文件 469
10.6.3 提供文檔文件服務(wù) 470
10.7 本章練習(xí) 472
10.8 本章小結(jié) 473
10.9 附加資源 473
第 11 章 代碼測試與性能分析 474
11.1 代碼優(yōu)化 474
11.2 基準測試代碼 475
11.2.1 重寫 main()函數(shù) 476
11.2.2 基準測試緩沖寫入和讀取 477
11.2.3 benchstat 實用工具 481
11.2.4 錯誤定義的基準測試函數(shù) 481
11.3 代碼性能分析 482
11.3.1 命令行應(yīng)用程序的性能分析 483
11.3.2 HTTP 服務(wù)器性能分析 486
11.3.3 Go 性能分析器的 Web 界面 488
11.4 go tool trace 實用程序 488
11.4.1 從客戶端追蹤 Web 服務(wù)器 491
11.4.2 訪問 Web 服務(wù)器的所有路由 494
11.5 測試 Go 代碼 499
11.5.1 編寫./ch03/intRE.go 測試 499
11.5.2 TempDir()函數(shù) 500
11.5.3 Cleanup()函數(shù) 501
11.5.4 testing/quick 包 503
11.5.5 超時測試 505
11.5.6 測試代碼覆蓋率 506
11.5.7 發(fā)現(xiàn) Go 語言中的不可達代碼 509
11.6 測試基于數(shù)據(jù)庫后端的 HTTP 服務(wù)器 510
11.7 模糊測試 516
11.8 交叉編譯 517
11.9 使用 go:generate 518
11.10 生成示例函數(shù) 521
11.11 本章練習(xí) 522
11.12 本章小結(jié) 523
11.13 附加資源 523
第 12 章 與 gRPC 協(xié)同工作 524
12.1 gRPC 簡介 524
12.2 定義接口定義語言文件 525
12.3 創(chuàng)建 gRPC 服務(wù)器 528
12.4 開發(fā) gRPC 客戶端 532
12.5 本章練習(xí) 536
12.6 本章小結(jié) 536
12.7 附加資源 537
第 13 章 Go 語言中的泛型 538
13.1 泛型簡介 538
13.2 約束條件 540
13.3 使用泛型定義新數(shù)據(jù)類型 543
13.4 接口和泛型 546
13.5 反射和泛型 549
13.6 本章練習(xí) 551
13.7 本章小結(jié) 551
13.8 附加資源 552
附錄 553