天天看點

開始讀 Go 源碼了

原文連結: 開始讀 Go 源碼了

學完 Go 的基礎知識已經有一段時間了,那麼接下來應該學什麼呢?有幾個方向可以考慮,比如說 Web 開發,網絡程式設計等。

在下一階段的學習之前,寫了一個開源項目|Go 開發的一款分布式唯一 ID 生成系統,如果你對這個項目感興趣的話,可以在 GitHub 上拿到源碼。

在寫項目的過程中,發現一個問題。實作功能是沒問題的,但不知道自己寫的代碼是不是符合 Go 的風格,是不是夠優雅。是以我覺得相比于繼續學習應用開發,不如向底層前進,打好基礎,打好寫 Go 代碼的基礎。

是以,我決定開始讀 Go 标準庫源碼,Go 一共有 150+ 标準庫,想要全部讀完的話不是不可能,但絕對是一項大工程,希望自己能堅持下去。

為什麼從 Go 标準庫的源碼開始讀呢?因為最近也看了一些 Go 底層原理的書,說實話,像 goroutine 排程,gc 垃圾回收這些内容,根本就看不懂。這要是一上來就讀這部分代碼,恐怕直接就放棄 Go 語言學習了。

而标準庫就不一樣了,有一部分代碼根本不涉及底層原理,實作也相對簡單,同時又能對 Go 的理念加深了解,作為入門再好不過了。然後再由簡入深,循序漸進,就像打怪更新一樣,一步一步征服 Go。

說了這麼多,那到底應該怎麼讀呢?我想到了一些方法:

看官方标準庫文檔。

看網上其他人的技術文章。

寫一些例子來練習如何使用。

如果可以的話,自己實作标準庫的功能。

将自己的閱讀心得總結輸出。

可以通過上面的一種或幾種方法相結合,然後再不斷閱讀不斷總結,最終找到一個完全适合自己的方法。

下面是我總結的一些标準庫及功能介紹:

<code>archive/tar</code> 和 <code>/zip-compress</code>:壓縮(解壓縮)檔案功能。

<code>fmt</code>-<code>io</code>-<code>bufio</code>-<code>path/filepath</code>-<code>flag</code>:

<code>fmt</code>:提供格式化輸入輸出功能。

<code>io</code>:提供基本輸入輸出功能,大多數是圍繞系統功能的封裝。

<code>bufio</code>:緩沖輸入輸出功能的封裝。

<code>path/filepath</code>:用來操作在目前系統中的目标檔案名路徑。

<code>flag</code>:提供對指令行參數的操作。

<code>strings</code>-<code>strconv</code>-<code>unicode</code>-<code>regexp</code>-<code>bytes</code>:

<code>strings</code>:提供對字元串的操作。

<code>strconv</code>:提供将字元串轉換為基礎類型的功能。

<code>unicode</code>:為 unicode 型的字元串提供特殊的功能。

<code>regexp</code>:正規表達式功能。

<code>bytes</code>:提供對字元型分片的操作。

<code>index/suffixarray</code>:子字元串快速查詢。

<code>math</code>-<code>math/cmath</code>-<code>math/big</code>-<code>math/rand-sort</code>:

<code>math</code>:基本的數學函數。

<code>math/cmath</code>:對複數的操作。

<code>math/rand</code>:僞随機數生成。

<code>sort</code>:為數組排序和自定義集合。

<code>math/big</code>:大數的實作和計算。

<code>container</code>-<code>/list</code>-<code>/ring</code>-<code>/heap</code>:

<code>list</code>:雙連結清單。

<code>ring</code>:環形連結清單。

<code>heap</code>:堆。

<code>compress/bzip2</code>-<code>/flate</code>-<code>/gzip</code>-<code>/lzw</code>-<code>zlib</code>:

<code>compress/bzip2</code>:實作 bzip2 的解壓。

<code>flate</code>:實作 deflate 的資料壓縮格式,如 RFC 1951 所述。

<code>gzip</code>:實作 gzip 壓縮檔案的讀寫。

<code>lzw</code>:Lempel Ziv Welch 壓縮資料格式實作。

<code>zlib</code>:實作 zlib 資料壓縮格式的讀寫。

<code>context</code>:用來簡化對于處理單個請求的多個 goroutine 之間與請求域的資料、取消信号、截止時間等相關操作。

<code>crypto</code>-<code>crypto/md5</code>-<code>crypto/sha1</code>:

<code>crypto</code>:常用密碼常數的集合。

<code>crypto/md5</code>:MD5 加密。

<code>crypto/sha1</code>:SHA1 加密。

<code>errors</code>:實作操作出錯的方法。

<code>expvar</code>:為公共變量提供标準化的接口。

<code>hash</code>:所有散列函數實作的通用接口。

<code>html</code>:HTML 文本轉碼轉義功能。

<code>sort</code>:提供用于對切片和使用者定義的集合進行排序的原始函數。

<code>unsafe</code>:包含了一些打破 Go 語言「類型安全」的指令,一般程式不會使用,可用在 C/C++ 程式的調用中。

<code>syscall</code>-<code>os</code>-<code>os/exec</code>:

<code>syscall</code>:提供了作業系統底層調用的基本接口。

<code>os</code>:提供給我們一個平台無關性的作業系統功能接口,采用類 Unix 設計,隐藏了不同作業系統間差異,讓不同的檔案系統和作業系統對象表現一緻。

<code>os/exec</code>:提供了運作外部作業系統指令和程式的方式。

<code>time</code>-<code>log</code>:

<code>time</code>:日期和時間的基本操作。

<code>log</code>:記錄程式運作時産生的日志。

<code>encoding/json</code>-<code>encoding/xml</code>-<code>text/template</code>:

<code>encoding/json</code>:讀取并解碼和寫入并編碼 JSON 資料。

<code>encoding/xml</code>:簡單的 XML1.0 解析器。

<code>text/template</code>:生成像 HTML 一樣的資料與文本混合的資料驅動模闆。

<code>net</code>-<code>net/http</code>:

<code>net</code>:網絡資料的基本操作。

<code>http</code>:提供了一個可擴充的 HTTP 伺服器和基礎用戶端,解析 HTTP 請求和回複。

<code>runtime</code>:Go 程式運作時的互動操作,例如垃圾回收和協程建立。

<code>reflect</code>:實作通過程式運作時反射,讓程式操作任意類型的變量。

這裡僅僅列舉了一部分标準庫,更全面的标準庫清單大家可以直接看官網。

那麼問題來了,這麼多庫從何下手呢?

我這裡做一個簡單的分類,由于水準有限,隻能做一些簡單的梳理,然後大家可以結合自己的實際情況來做選擇。

有些庫涉及到非常專業的知識,投入産出比可能會比較低。比如 <code>archive</code>、<code>compress</code> 以及 <code>crypto</code>,涉及到壓縮算法以及加密算法的知識。

有些庫屬于工具類,比如 <code>bufio</code>、<code>bytes</code>、<code>strings</code>、<code>path</code>、<code>strconv</code> 等,這些庫不涉及領域知識,閱讀起來比較容易。

有些庫屬于與作業系統打交道的,比如 <code>os</code>,<code>net</code>、<code>sync</code> 等,學習這些庫需要對作業系統有明确的認識。

<code>net</code> 下的很多子包與網絡協定相關,比如 <code>net/http</code>,涉及 <code>http</code> 封包的解析,需要對網絡協定比較了解。

如果想要深入了解語言的底層原理,則需要閱讀 <code>runtime</code> 庫。

要想快速入門,并且了解語言的設計理念,建議閱讀 <code>io</code> 以及 <code>fmt</code> 庫,閱讀後會對接口的設計了解更深。

我已經看了一些源碼,雖然過程痛苦,但确實非常有用。前期可能了解起來比較困難,用的時間長一些,但形成固定套路之後,會越來越熟悉,用的時間也會更少,了解也會更深刻。

後續我還會繼續總結輸出,請大家持續關注,讓我們學起來。

開源項目:

https://github.com/yongxinz/id-maker

往期文章:

開源項目|Go 開發的一款分布式唯一 ID 生成系統

測試小姐姐問我 gRPC 怎麼用,我直接把這篇文章甩給了她

gRPC,爆贊