Go語言高級編程(第2版)
柴樹杉 曹春暉
相關主題
商品描述
本書從實踐出發,全面講解Go語言的高級編程技術和應用場景,涵蓋Go語言的底層機制、性能優化、系統編程及前沿應用等多個方面。全書共10章,第1章回顧Go語言的發展歷程,幫助讀者理解其設計理念和演進過程;第2章和第3章系統介紹CGO編程與Go匯編語言的使用方法,使讀者能夠高效調用C庫並深入理解Go的底層實現:第4章和第5章深入解析Go運行時和編譯器,包括內存管理、調度器、垃圾收集機制等相關技術;第6章和第7章探討Go在RPC和 Web編程中的應用,介紹Protobuf、 gRPC等核心技術,並剖析Web框架的設計和優化方案;第8章和第9章拓展Go的應用邊界,涵蓋 WebAssembly 和GUI 編程,使Go語言不僅限於服務器端編程;第10章新增Go語言與大模型的結合,探索人工智能技術在Go生態系統中的應用場景。
本書適合對Go語言有一定基礎,希望深入理解其底層機制和高級應用的開發者閱讀。無論是系統工程師、後端開發者,還是對Go語言運行時、編譯器及新興技術感興趣的Go程序員,都能在本書中找到翔實的技術解析和實踐指南,達到高效開發和技術進階的目的。
作者簡介
柴樹杉,Go語言代碼貢獻者,凹語言聯合發起人,編程語言開放社區(PLOC)發起人。著有《Go語言定制指南》和《WebAssembly標準入門》等書。現致力於推動國產編程語言、少兒編程技術的發展。
曹春暉,在Web領域工作多年,開源愛好者。構建過多個大型網站系統,對大型網站系統的架構和性能有深刻理解。
王敏,畢業於中國地質大學(武漢)藝術設計(動畫方向)專業。參與《桃花源記》等網遊界面設計,現深耕兒童藝術教育,所著《兒童創意彩鉛》以專業視角開啟少兒美學新境界。
目錄大綱
目錄
第 1章 Go語言基礎 1
1.1 Go語言創世紀 1
1.1.1 來自貝爾實驗室特有基因 2
1.1.2 你好,世界 4
1.2 “Hello, World”的革命 4
1.2.1 B語言—Ken Thompson,1969 5
1.2.2 C語言—Dennis Ritchie,1972—1989 5
1.2.3 Newsqueak—Rob Pike,1989 6
1.2.4 Alef—Phil Winterbottom,1993 8
1.2.5 Limbo—Sean Dorward,PhilWinterbottom,Rob Pike,1995 10
1.2.6 Go語言—2007—2009 10
1.2.7 你好,世界!—2.0版本 12
1.3 數組、字符串和切片 13
1.3.1 數組 13
1.3.2 字符串 16
1.3.3 切片 21
1.4 函數、方法和接口 27
1.4.1 函數 27
1.4.2 方法 31
1.4.3 接口 35
1.5 面向並發的內存模型 39
1.5.1 goroutine和系統線程 40
1.5.2 原子操作 40
1.5.3 順序一致性內存模型 44
1.5.4 初始化順序 45
1.5.5 goroutine的創建 46
1.5.6 基於通道的通信 46
1.5.7 不靠譜的同步 48
1.6 泛型編程 49
1.6.1 認識Go語言的泛型 49
1.6.2 泛型和接口 50
1.6.3 運行時Cloner[T]和T類型的區別 52
1.6.4 泛型後方法淪為“二等公民” 53
1.6.5 方法不支持泛型的原因 54
1.6.6 Go語言的泛型為何用方括號 54
1.7 自定義疊代器 55
1.7.1 使用疊代器 55
1.7.2 疊代器的定義 56
1.7.3 疊代器的原理 57
1.7.4 loopvar語義調整 58
1.8 補充說明 59
第 2章 CGO編程 60
2.1 快速入門 60
2.1.1 最簡CGO程序 60
2.1.2 基於C標準庫函數輸出字符串 61
2.1.3 使用自己的C語言函數 61
2.1.4 C代碼的模塊化 62
2.1.5 用Go重新實現C語言函數 63
2.1.6 面向C語言接口的Go編程 64
2.2 CGO基礎 65
2.2.1 import "C"語句 65
2.2.2 #cgo命令 67
2.2.3 build標誌條件編譯 68
2.3 類型轉換 69
2.3.1 數值類型的轉換 69
2.3.2 Go字符串和切片的轉換 71
2.3.3 結構體、聯合和枚舉類型的轉換 72
2.3.4 數組、字符串和切片的轉換 75
2.3.5 指針間的轉換 78
2.3.6 數值和指針的轉換 79
2.3.7 切片間的轉換 79
2.4 函數調用 80
2.4.1 Go調用C語言函數 80
2.4.2 C語言函數的返回值 81
2.4.3 void函數的返回值 82
2.4.4 C調用Go導出函數 83
2.5 內存模型 84
2.5.1 Go訪問C內存 84
2.5.2 C臨時訪問傳入的Go內存 85
2.5.3 C長期持有Go指針對象 87
2.5.4 導出C語言函數不能返回Go內存 88
2.5.5 runtime.Pinner類型 89
2.6 C++類封裝 90
2.6.1 C++類到Go語言對象 90
2.6.2 Go語言對象到C++類 95
2.6.3 徹底解放C++的this指針 98
2.7 MOSN帶來的優化 100
2.8 補充說明 101
第3章 Go匯編語言 102
3.1 快速入門 102
3.1.1 實現和聲明 102
3.1.2 定義整型變量 103
3.1.3 定義字符串類型變量 104
3.1.4 定義main()函數 107
3.1.5 特殊字符 108
3.1.6 沒有分號 108
3.2 計算機體系結構 108
3.2.1 圖靈機和Brainfuck語言 109
3.2.2 《人力資源機器》遊戲 110
3.2.3 x86-64體系結構 111
3.2.4 Go匯編中的偽寄存器 112
3.2.5 x86-64指令集 113
3.2.6 ARM64指令集 115
3.3 常量和全局變量 116
3.3.1 常量 116
3.3.2 全局變量 117
3.3.3 變量的內存布局 121
3.3.4 標識符規則和特殊標誌 123
3.4 函數 123
3.4.1 基本語法 123
3.4.2 函數參數和返回值 125
3.4.3 參數和返回值的內存布局 126
3.4.4 函數中的局部變量 128
3.4.5 調用其他函數 130
3.4.6 宏函數 132
3.5 控制流 132
3.5.1 順序執行 132
3.5.2 if/goto跳轉 135
3.5.3 for循環 136
3.6 再論函數 138
3.6.1 函數調用規範 138
3.6.2 高級匯編語言 139
3.6.3 PCDATA和FUNCDATA 141
3.6.4 遞歸函數:1到n求和 144
3.6.5 閉包函數 146
3.6.6 調用約定 148
3.7 匯編語言的威力 148
3.7.1 系統調用 148
3.7.2 直接調用C語言函數 150
3.7.3 AVX指令集 152
3.8 補充說明 153
第4章 Go運行時 155
4.1 運行時概覽 155
4.1.1 調度器 155
4.1.2 內存分配器 156
4.1.3 垃圾收集器 156
4.1.4 網絡輪詢器 156
4.1.5 小結 156
4.2 調度器 157
4.2.1 生產者細節 157
4.2.2 消費者細節 158
4.2.3 任務隊列細節 159
4.2.4 處理阻塞 159
4.2.5 理解調度和延遲的關系 162
4.2.6 小結 164
4.3 內存分配器 164
4.3.1 逃逸分析 164
4.3.2 操作系統內存管理的二次抽象 165
4.3.3 內存分配器簡介 166
4.3.4 理解Go的內存占用 168
4.3.5 小結 171
4.4 垃圾收集器 171
4.4.1 語法垃圾和語義垃圾 171
4.4.2 並發標記清掃的核心流程 172
4.4.3 與Java分代機制的對比 173
4.4.4 一些常見的優化思路 175
4.4.5 小結 175
4.5 網絡輪詢器 175
4.5.1 傳統網絡編程 176
4.5.2 Go對操作系統的網絡API的封裝 177
4.5.3 阻塞易理解,回調難理解 177
4.5.4 goroutine的掛起和喚醒流程 179
4.5.5 網絡輪詢器的缺陷 180
4.5.6 小結 181
4.6 運行時性能分析 181
4.6.1 安裝依賴的Graphviz工具 181
4.6.2 CPU性能測試分析 182
4.6.3 內存分配性能測試分析 183
4.6.4 在程序中增加性能分析 184
4.6.5 性能分析引導的優化 185
4.6.6 持續性能分析 185
4.6.7 堆內存性能分析 188
4.6.8 小結 189
4.7 補充說明 189
第5章 Go編譯器 190
5.1 表達式 190
5.1.1 基礎表達式語法 190
5.1.2 表達式的語法分析 191
5.1.3 求值表達式 193
5.1.4 標識符:為表達式中引入變量 193
5.2 類型檢查 195
5.2.1 語義錯誤 195
5.2.2 go/types包 196
5.2.3 跨包的類型檢查 197
5.2.4 小結 200
5.3 語義分析 200
5.3.1 名字空間 200
5.3.2 整體架構 203
5.3.3 小結 204
5.4 SSA 中間代碼 204
5.4.1 SSA簡介 204
5.4.2 生成SSA 204
5.4.3 SSA解釋運行 208
5.4.4 SSA包的架構 209
5.4.5 小結 210
5.5 LLVM後端 210
5.5.1 最小編譯器 211
5.5.2 表達式手動轉換到LLVM IR程序 212
5.5.3 表達式自動轉換到LLVM IR程序 212
5.5.4 小結 214
5.6 示例:檢查append參數 214
5.6.1 append()函數的參數陷阱 214
5.6.2 Go語言社區的不同觀點 215
5.6.3 統計真實代碼發現問題 215
5.6.4 go vet自動識別這類問題 216
5.7 補充說明 217
第6章 RPC和Protobuf 218
6.1 RPC入門 218
6.1.1 RPC版“Hello, World” 218
6.1.2 更安全的RPC接口 219
6.1.3 跨語言的RPC 222
6.1.4 HTTP上的RPC 224
6.2 Protobuf 225
6.2.1 Protobuf入門 225
6.2.2 定制代碼生成插件 227
6.2.3 自動生成完整的RPC代碼 230
6.3 玩轉RPC 233
6.3.1 客戶端RPC的實現原理 233
6.3.2 基於RPC實現監視功能 234
6.3.3 反向RPC 237
6.3.4 上下文信息 238
6.4 gRPC入門 239
6.4.1 gRPC技術棧 239
6.4.2 gRPC簡介 240
6.4.3 gRPC流 241
6.4.4 發布/訂閱模式 244
6.5 gRPC進階 247
6.5.1 證書認證 247
6.5.2 令牌認證 251
6.5.3 截取器 253
6.5.4 與Web服務共存 254
6.6 gRPC和Protobuf擴展 255
6.6.1 驗證器 256
6.6.2 REST風格的接口 258
6.6.3 Nginx 261
6.7 基於Protobuf的框架pbgo 261
6.7.1 Protobuf擴展語法 262
6.7.2 插件中讀取擴展信息 263
6.7.3 生成REST風格的接口的代碼 264
6.7.4 啟動REST服務 266
6.8 補充說明 266
第7章 Go Web編程 267
7.1 Go Web編程簡介 267
7.2 請求路由 270
7.2.1 HttpRouter簡介 271
7.2.2 HttpRouter原理 273
7.2.3 壓縮檢索樹創建過程 274
7.3 中間件 278
7.3.1 代碼泥潭 278
7.3.2 使用中間件剝離非業務邏輯 280
7.3.3 更優雅的中間件寫法 282
7.3.4 在中間件中適合做哪些事情 283
7.4 請求驗證 284
7.4.1 重構請求驗證函數 285
7.4.2 用請求驗證器減少重復勞動 286
7.4.3 請求驗證器原理 287
7.5 與數據庫交互 290
7.5.1 從database/sql講起 290
7.5.2 提高生產效率的ORM和SQL構建器 292
7.5.3 隱式SQL導致線上故障 294
7.5.4 基於SQLC的數據層開發 295
7.6 服務流量限制 296
7.6.1 流量限制算法——令牌桶算法 298
7.6.2 令牌桶算法原理 300
7.6.3 服務瓶頸和QoS 302
7.7 大型Web項目的分層 302
7.8 接口和表驅動開發 308
7.8.1 業務系統的發展過程 308
7.8.2 使用函數封裝業務流程 308
7.8.3 使用接口進行抽象 309
7.8.4 接口的優缺點 312
7.8.5 表驅動開發 313
7.9 灰度發布 314
7.9.1 通過分批次部署實現灰度發布 314
7.9.2 通過業務規則進行灰度發布 315
7.9.3 如何實現灰度發布規則 317
7.10 現代Go語言後端編程 320
7.10.1 Go Micro 321
7.10.2 Kratos 322
7.10.3 go-zero 322
7.10.4 小結 323
7.11 補充說明 323
第8章 Go和WebAssembly 324
8.1 WebAssembly簡介 324
8.1.1 誕生背景 324
8.1.2 終將被編譯為WebAssembly 325
8.2 你好,WebAssembly 325
8.2.1 用Go語言生成並執行WebAssembly模塊 325
8.2.2 在Node.js中執行WebAssembly模塊 326
8.2.3 在瀏覽器中執行WebAssembly模塊 326
8.2.4 小結 328
8.3 外部函數接口 328
8.3.1 使用JavaScript函數 328
8.3.2 回調Go語言函數 330
8.3.3 syscall/js包 332
8.3.4 WebAssembly模塊的導入函數 334
8.3.5 WASI規範 337
8.4 WebAssembly虛擬機 337
8.4.1 構建WebAssembly模塊 337
8.4.2 通過虛擬機執行 338
8.4.3 小結 338
8.5 示例:WebAssembly插件 338
8.5.1 MOSN的WebAssembly插件
架構設計 339
8.5.2 認識Proxy-Wasm規範 339
8.5.3 處理HTTP請求示例 341
8.5.4 小結 343
8.6 導出Go語言函數 343
8.6.1 構建WebAssembly模塊 343
8.6.2 執行WebAssembly模塊 344
8.6.3 運行時限制 345
8.7 補充說明 345
第9章 Go GUI編程 346
9.1 Shiny框架入門 346
9.1.1 Hello, Shiny 346
9.1.2 顯示圖像 347
9.1.3 核心組件 348
9.1.4 底層驅動程序 349
9.2 Fyne框架入門 350
9.2.1 安裝環境 350
9.2.2 安裝Fyne核心庫 350
9.2.3 Hello, Fyne 350
9.2.4 回調函數 351
9.2.5 對話框 352
9.2.6 畫布 354
9.2.7 布局管理 363
9.2.8 Fyne在瀏覽器中 367
9.3 Walk框架入門 370
9.3.1 你好, Walk 370
9.3.2 聲明式語法 371
9.3.3 通過.manifest文件指定依賴 372
9.3.4 內置.manifest文件 373
9.3.5 給可執行程序添加圖標 373
9.3.6 添加版本信息 374
9.3.7 Walk的工作原理 375
9.4 國際化支持 379
9.4.1 你好,世界! 379
9.4.2 國際化實現原理 379
9.4.3 你好,世界!多語言版 380
9.4.4 制作翻譯文件 380
9.4.5 本地的語言環境 381
9.4.6 為何如此煩瑣 381
9.5 補充說明 381
第 10章 大模型 382
10.1 AI機器人gabyhelp 382
10.1.1 Gaby框架 382
10.1.2 如何接入大語言模型 384
10.1.3 小結 386
10.2 DeepSeek 386
10.2.1 生成API key 386
10.2.2 Go語言SDK 387
10.2.3 Go語言驗證服務 389
10.2.4 多輪對話補全 389
10.2.5 推理模型 390
10.2.6 交互式對話 391
10.2.7 小結 393
10.3 LangChain for Go 393
10.3.1 連接OpenAI的大模型 393
10.3.2 連接DeepSeek 393
10.3.3 構建大模型聊天應用 394
10.3.4 小結 398
10.4 Ollama 398
10.4.1 安裝Ollama 398
10.4.2 下載大模型 399
10.4.3 運行大模型 400
10.4.4 本地大模型驅動聊天應用 401
10.4.5 小結 402
10.5 大模型智能體 402
10.5.1 計算常量表達式 402
10.5.2 集成到大模型流程中 402
10.5.3 應用到聊天服務中 404
10.5.4 小結 405
10.6 補充說明 405
後記 406