## Go語言項目
所有的編程語言都反映了語言設計者對編程哲學的反思,通常包括之前的語言所暴露的一些不足地方的改進。Go項目是在Google公司維護超級復雜的幾個軟件系統遇到的一些問題的反思(但是這類問題絕不是Google公司所特有的)。
正如[Rob Pike](http://genius.cat-v.org/rob-pike/)所說,“軟件的復雜性是乘法級相關的”,通過增加一個部分的復雜性來修復問題通常將慢慢地增加其他部分的復雜性。通過增加功能、選項和配置是修復問題的最快的途徑,但是這很容易讓人忘記簡潔的內涵,即從長遠來看,簡潔依然是好軟件的關鍵因素。
簡潔的設計需要在工作開始的時候舍棄不必要的想法,并且在軟件的生命周期內嚴格區別好的改變和壞的改變。通過足夠的努力,一個好的改變可以在不破壞原有完整概念的前提下保持自適應,正如[Fred Brooks](http://www.cs.unc.edu/~brooks/)所說的“概念完整性”;而一個壞的改變則不能達到這個效果,它們僅僅是通過膚淺的和簡單的妥協來破壞原有設計的一致性。只有通過簡潔的設計,才能讓一個系統保持穩定、安全和持續的進化。
Go項目包括編程語言本身,附帶了相關的工具和標準庫,最后但并非代表不重要的是,關于簡潔編程哲學的宣言。就事后諸葛的角度來看,Go語言的這些地方都做的還不錯:擁有自動垃圾回收、一個包系統、函數作為一等公民、詞法作用域、系統調用接口、只讀的UTF8字符串等。但是Go語言本身只有很少的特性,也不太可能添加太多的特性。例如,它沒有隱式的數值轉換,沒有構造函數和析構函數,沒有運算符重載,沒有默認參數,也沒有繼承,沒有泛型,沒有異常,沒有宏,沒有函數修飾,更沒有線程局部存儲。但是,語言本身是成熟和穩定的,而且承諾保證向后兼容:用之前的Go語言編寫程序可以用新版本的Go語言編譯器和標準庫直接構建而不需要修改代碼。
Go語言有足夠的類型系統以避免動態語言中那些粗心的類型錯誤,但是,Go語言的類型系統相比傳統的強類型語言又要簡潔很多。雖然,有時候這會導致一個“無類型”的抽象類型概念,但是Go語言程序員并不需要像C++或Haskell程序員那樣糾結于具體類型的安全屬性。在實踐中,Go語言簡潔的類型系統給程序員帶來了更多的安全性和更好的運行時性能。
Go語言鼓勵當代計算機系統設計的原則,特別是局部的重要性。它的內置數據類型和大多數的準庫數據結構都經過精心設計而避免顯式的初始化或隱式的構造函數,因為很少的內存分配和內存初始化代碼被隱藏在庫代碼中了。Go語言的聚合類型(結構體和數組)可以直接操作它們的元素,只需要更少的存儲空間、更少的內存寫操作,而且指針操作比其他間接操作的語言也更有效率。由于現代計算機是一個并行的機器,Go語言提供了基于CSP的并發特性支持。Go語言的動態棧使得輕量級線程goroutine的初始棧可以很小,因此,創建一個goroutine的代價很小,創建百萬級的goroutine完全是可行的。
Go語言的標準庫(通常被稱為語言自帶的電池),提供了清晰的構建模塊和公共接口,包含I/O操作、文本處理、圖像、密碼學、網絡和分布式應用程序等,并支持許多標準化的文件格式和編解碼協議。庫和工具使用了大量的約定來減少額外的配置和解釋,從而最終簡化程序的邏輯,而且,每個Go程序結構都是如此的相似,因此,Go程序也很容易學習。使用Go語言自帶工具構建Go語言項目只需要使用文件名和標識符名稱, 一個偶爾的特殊注釋來確定所有的庫、可執行文件、測試、基準測試、例子、以及特定于平臺的變量、項目的文檔等;Go語言源代碼本身就包含了構建規范。
- 前言
- Go語言起源
- Go語言項目
- 本書的組織
- 更多的信息
- 致謝
- 入門
- Hello, World
- 命令行參數
- 查找重復的行
- GIF動畫
- 獲取URL
- 并發獲取多個URL
- Web服務
- 本章要點
- 程序結構
- 命名
- 聲明
- 變量
- 賦值
- 類型
- 包和文件
- 作用域
- 基礎數據類型
- 整型
- 浮點數
- 復數
- 布爾型
- 字符串
- 常量
- 復合數據類型
- 數組
- Slice
- Map
- 結構體
- JSON
- 文本和HTML模板
- 函數
- 函數聲明
- 遞歸
- 多返回值
- 錯誤
- 函數值
- 匿名函數
- 可變參數
- Deferred函數
- Panic異常
- Recover捕獲異常
- 方法
- 方法聲明
- 基于指針對象的方法
- 通過嵌入結構體來擴展類型
- 方法值和方法表達式
- 示例: Bit數組
- 封裝
- 接口
- 接口是合約
- 接口類型
- 實現接口的條件
- flag.Value接口
- 接口值
- sort.Interface接口
- http.Handler接口
- error接口
- 示例: 表達式求值
- 類型斷言
- 基于類型斷言識別錯誤類型
- 通過類型斷言查詢接口
- 類型分支
- 示例: 基于標記的XML解碼
- 補充幾點
- Goroutines和Channels
- Goroutines
- 示例: 并發的Clock服務
- 示例: 并發的Echo服務
- Channels
- 并發的循環
- 示例: 并發的Web爬蟲
- 基于select的多路復用
- 并發的退出
- 示例: 聊天服務
- 基于共享變量的并發
- 競爭條件
- sync.Mutex互斥鎖
- sync.RWMutex讀寫鎖
- 內存同步
- 競爭條件檢測
- 示例: 并發的非阻塞緩存
- Goroutines和線程
- 包和工具
- 包簡介
- 導入路徑
- 包聲明
- 導入聲明
- 包的匿名導入
- 包和命名
- 工具
- 測試
- go test
- 測試函數
- 測試覆蓋率
- 基準測試
- 剖析
- 示例函數
- 反射
- 為何需要反射?
- reflect.Type和reflect.Value
- Display遞歸打印
- 示例: 編碼S表達式
- 通過reflect.Value修改值
- 示例: 解碼S表達式
- 顯示一個類型的方法集
- 幾點忠告
- 底層編程
- unsafe.Sizeof, Alignof 和 Offsetof
- unsafe.Pointer
- 示例: 深度相等判斷
- 通過cgo調用C代碼
- 幾點忠告
- 附錄
- 附錄A:原文勘誤
- 附錄B:作者譯者
- 附錄C:譯文授權
- 附錄D:其它語言