Go 回答之如何閱讀 Go 源碼

我的知乎回答,問題是關於如何閱讀 Go 源碼。地址


Go 的源碼在安裝包的 src/ 目錄下。怎麼看它的源碼呢?直接看吧!沒人教的情況下,只能自己擼了。當然,這種內容一般也不會有人教。

怎麼擼?

Go 源碼中,應該可分爲與語言息息相關的部分,和官方提供的標準庫。與語言實現相關的肯定是最難的,不是那麼容易理解。可以先主要看標準庫,其他的可以先大概瞭解下。

先把源碼目錄整體掃一遍,大概看看涉及了哪些模塊,然後再挑自己喜歡的部分進行更深一步的學習與研究。建議每個目錄都簡單寫個 hello world,如此的體悟會更深。如果連 hello world 也寫不出來,這個模塊的源碼暫時就沒必要研究了,先學好基礎吧。畢竟,包的使用不僅與語言相關,還涉及具體場景和實現原理,這都是要學習的。

對包的使用熟悉理解後,就可以閱讀源碼了,但此時最好還是不要太摳細節,求理解涉及設計思想,整體流程。源碼閱讀可以通過畫 UML 的方式輔助,從縱向和橫向幫助理解。代碼設計時,一般最容易想到的就是按順序方式寫,很快就能搞定。但當項目變大,抽象的模塊會越來越多,抽象出接口和具體的實現,實現可能包含其他類型的組合。搞明白這些關係,對於理解源碼實現會較有幫助。

如果能順利經過前面兩步,接下來的源碼閱讀就比較簡單了。而且 Go 語言的特點就是簡潔易讀,沒什麼語法糖。當然,如果是一些實現比較複雜的包,你還需知道它們的底層原理,就比如 net/http 包,你得對 http 協議熟悉到一定程度,纔可能從細節研究源碼實現。

可能是我閒的蛋疼,準備試着先從第一步出發,整體擼一下 Go 的源碼中包含的模塊,沒事的時候就更新一點進去。等把這些大致擼完一遍,感覺我的 Golang 之旅 專欄又可以多出很多寫作素材了。

我的環境是 Go 1.11。關於每個模塊,我會把讀過的一些文章放在下面,由於只是粗略閱讀,並不能保證讀過的每篇文章都是精品。

補充:

2019年8月8日 凌晨 01:13, 大概花了兩個多星期的零碎時間,簡單擼完了一版。總的感覺,還是有很多地方理解不夠,希望後面可以按前面說的思路,按包逐步進行源碼解剖。


archive

包含了文件歸檔的相關內容,其中涉及了兩個包,分別是 tar 和 zip。

archive/tar,即歸檔,如果瞭解 Linux 下的 tar 命令,可與之對應理解。如果要在歸檔基礎上進行壓縮,還要藉助 compress 下的相關包。提醒一點,是使用時要注意理解歸檔與壓縮的區別。

相關閱讀:

鳥哥的文件與文件系統的壓縮與打包
archive/tar 實現打包壓縮及解壓

archive/zip,與 zip 格式壓縮文件操作相關的包,使用方法與 tar 很類似。在尋找與 zip 包相關的資料時,瞭解到 zip 的作者年僅 37 歲就逝世了,而全世界所有使用 zip 壓縮的文件開頭部分都有他的名字 "PK",而我們識別一個文件是否是 zip 正是通過這種方法。

相關閱讀:

archive/zip 實現壓縮與解壓
zip 的百度百科

bufio

實現了緩衝 IO 的功能,通過包裹 io.Reader 或 io.Writer 函數創建新的 Reader 或 Writer 實例,並且這些新創建的實例提供了緩衝的能力。使用方法非常簡單,達到指定緩衝大小,觸發寫或讀操作,如未達到要求,可用 Flush 方法刷新。

相關閱讀:

Introduction to bufio package in Golang
In-depth introduction to bufio.Scanner in Golang
bufio - 緩存 IO

builtin

Go 語言中的內置類型、函數、變量、常量的聲明。暫時看來,沒啥可深入閱讀的,應該結合 Go 的內部實現進行閱讀。

bytes

主要是關於 byte slice 操作的一些函數。由於 []byte 也可用於表示 string,故其中的函數、方法與 strings 很類似,比如 Join、Split、Trim、 Contains 等。

相關閱讀:

Go 語言學習 - bytes 包
Go Walkthrough: bytes+ + strings

cmd

Go 命令工具集的實現代碼,如 go、gofmt、godoc、pprof 等,應該主要是和 Go 語言實現相關性較大,比較底層。每個命令都夠研究一段時間了,特別是 go 命令,並且前提是你的計算機底層原理的功底要足夠優秀。

網上搜索下,關於它的資料比較少。

相關閱讀:

Go 官網之 Command go

compress

之前提到 archive 包中是歸檔相關操作,而相對的 compress 包主要與壓縮相關。主要實現了幾種主流的壓縮格式,如 bzip2、flate、gzip、lzw、zlib。

compress/bzip2,常見的 .bz2 結尾的壓縮文件格式基本可用這個包操作,要與 tar 結合使用。

compress/gzip,常見的 .gz 結尾的壓縮文件格式基本可用這個包操作,要與 tar 結合使用。

compress/flate,flate 應該主要是 zip 用的壓縮算法,如果閱讀了前面的 archive/zip 的源碼,就會發現其中導了這個包。

compress/zlib, compress/lzw 基本與上面同理,應該都是某種壓縮算法實現。因爲我對壓縮算法沒什麼太深的研究,暫時瞭解個大概就好了,希望沒有介紹錯誤。

相關閱讀:

Go 官網之 compress

container

我們知道,Go 內置的數據結構很少,只有數組、切片和映射。除此以外,其實還有部分的結構放在了 container 包中,heap 堆、list 雙端隊列,ring 迴環隊列。

它們的使用非常簡單,基本就是增刪改查。

相關閱讀:

container 容器數據類型:heap、list 和 ring

context

讀這個包之前,得首先熟悉 Go 的併發代碼如何編寫,瞭解 Done channel 如何實現向所有 goroutine 發送廣播信號。Go 的併發單元稱爲 goroutine,但是不同 goroutine 之間並沒有父子兄弟關係,爲了更好地併發控制,context 包就誕生了。它可以實現在不同 goroutine 間安全地傳遞數據以及超時管理等。

相關閱讀:

Go 譯文之通過 context 實現併發控制
深度解密 Go 語言之 Context

crypto

加密相關,涉及內容有點多,包含了各種常用的加密算法實現,比如對稱加密啊 AES、DES 等,公私鑰加密 rsa、dsa 等,散列算法 sha1、sha256 等,隨機數 rand 也有,不知道和 math 的隨機有什麼區別。沒有找到一篇綜合性介紹的文章,畢竟比較複雜了,如果要看它們的源碼,得先要大概瞭解下每個加密算法的原理,纔好逐一突破。

相關閱讀:

Go 官網之 crypto

database

封裝了一套用於數據庫操作的通用接口,實現了數據庫連接管理,支持連接池功能。真正使用時,我們需要引入相應的驅動,才能實現指定類型數據庫的操作。

一個簡單的例子。

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    db, err := sql.Open("mysql", "username:password@tcp(127.0.0.1:3306)/test")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
}

github.com/go-sql-driver/mysql 便是提供的 MySQL 驅動。具體的查詢執行都是通過調用驅動實現的 db 接口中的方法。

相關閱讀:

database/sql-SQL/SQL-Like 數據庫操作接口
關於Golang中database/sql包的學習筆記

debug

和調試相關,具體內容比較複雜,我也不是很懂。內部有幾個包,如 dwarf、elf、gosym、macho、pe、plan9obj。

dwarf,可用於訪問可執行文件中的 DWARF 信息。具體什麼是 DWARF 信息呢?官網有個 PDF,具體介紹了什麼是 DWARF,有興趣可以看看。它主要是爲 UNIX 下的調試器提供必要的調試信息,例如 PC 地址對應的文件名行號等信息,以方便源碼級調試。

相關閱讀:

dwarf-2.0.0 調試信息格式
DWARF, 說不定你也需要它哦

elf,用於訪問 elf 類型文件。elf,即可執行與可連接格式,常被稱爲 ELF 格式,有三種類型:

  • 可重定位的對象文件(Relocatable file),由彙編器彙編生成的 .o 文件
  • 可執行性的對象文件(Executable file),可執行應用程序
  • 可被共享的對象文件(Shared object file),動態庫文件,也即 .so 文件

相關閱讀:

readelf elf文件格式分析
The 101 of ELF files on Linux: Understanding and Analysis

gosym,用於訪問 Go 編譯器生成的二進制文件之中的 Go 符號和行信息等,暫時還沒怎麼看。在 medium 發現個系列文章,介紹了 Go 中 debug 調試器的實現原理,相關閱讀部分是系列的第二篇文章。

相關閱讀:

Making debugger in Golang (part II)

macho,用於訪問 Mach-O object 格式文件。要閱讀這段源碼,同樣需要先了解什麼是 Mach-O,它是 Mach object 文件格式的縮寫,用於可執行文件、目標代碼、內核轉儲的文件格式。

相關閱讀:

維基百科-Mach-O
Go package - debug/macho

pe,實現了訪問 PE 格式文件,PE 是 Windows 系統可移植的可執行文件格式。

相關閱讀:

WIKI - Portable Executable
Go package - debug/pe

plan9obj,用於訪問 plan9 object 格式文件。

暫未找到關於 plan9object 的介紹文章。我們主要學習的話,主要應該是集中在 elf 和 gosym 兩個格式。

相關閱讀:

Go package - debug/plan9obj

encoding

主要關於我們常用到的各種數據格式的轉化操作,或也可稱爲編解碼,比如 JSON、XML、CSV、BASE64 等,主要的模塊有:

encoding/json,json 處理相關的模板,通用方式,我們可以將解析結果放到 map[string]interface{} 解析,也可以創建通用結構體,按 struct 方式進行。

encoding/xml,基本和 encoding/json 類似。但因爲 XML 比 json 要複雜很多,還涉及一些高級用法,比如與元素屬性相關等操作。

encoding/csv,csv 數據格式解析。

encoding/binary,可用於處理最底層的二進制數據流,按大小端實現 []byte 和整型數據之間的轉化。

其他諸如 hex、gob、base64、base32、gob、pem、ascii84 等數據格式的操作都是類似的,有興趣可以都嘗試一下。

相關閱讀:

Golang 下的 encoding 相關模塊的使用
Go 標準庫文檔翻譯之 encoding/xml
Golang 中 byte 轉 int 涉及到大小端問題嗎
使用 Go 語言標準庫對 CSV 文件進行讀寫
Go Walkthrough: encoding package

errors

Go 的錯誤處理主要代碼就是它。很遺憾的是,打開源碼後發現,就幾行代碼哦。主要是因爲 Go 的錯誤類型只是一個接口而已,它的源碼非常簡單。

package errors

// New returns an error that formats as the given text.
func New(text string) error {
    return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
    s string
}

func (e *errorString) Error() string {
    return e.s
}

Go 默認只提供了最簡單的實現,就上面這幾行代碼。真的是 awesome、amazing,哈哈。但正是因爲簡單,擴展出自己的 error 變得很簡單。比如,有些開發者認爲 Go 的錯誤處理太簡單,開發了一些包含 call stack trace 的 error 包。

相關閱讀:

github.com/pkg/errors
error-handling-and-go
What I Don’t Like About Error Handling in Go

expvar

主要是用於 Go 程序運行時的指標記錄,如 HTTP 服務在加入 expvar 後,我們可以通過 /debug/vars 返回這些指標,返回的數據是 JSON 格式的。

它的源碼不多,也就大約 300 行代碼,重點在它使用方法。

相關閱讀:

標準庫 EXPVAR 實戰
Monitoring apps with expvars and Go

flag

用於命令行參數解析的包,比如類似命令參數 grep -v grep,具體操作的時候要獲取 -v 後的參數值。很常用的功能,如果純粹自己實現是比較繁瑣的。

相關閱讀:

flag-命令行參數解析

fmt

從包名就可以知道,fmt 主要和格式化相關,關於什麼的格式化呢?主要是字符串的格式化,它的用法和 C 中 printf 都很類似。當然,除了實現 C 的用法,還提供了一些 Go 特有的實現。

相關閱讀:

Go Walkthrough: fmt

go

似乎是核心工具使用的包。

hash

hash 包主要定義了不同的 hash 算法的統一接口。而具體的 hash 算法實現有的直接 hash 的下層,比如 crc32、crc64,即 32 位循環冗餘校驗算法和 64 位循環冗餘校驗算法。而 md5 hash 算法在 crypto/md5 下,同樣實現了 hash 的相關接口。

相關閱讀:

常見哈希函數 FNV 和 MD5

html

Go 標準庫裏的 html 包功能非常簡單,大概了看下,主要是關於 html 文本的處理,例如該如何對 html 代碼做轉義。如果想支持 html 的解析,go 官方 github 下還提供了一個 net 倉庫,其中有個 html 的工具包。而 goquery 也是基於它實現的。

標準庫的 html 目錄下還有 template,html 的模板渲染工具,通過與 net/http 相結合,再加上一個數據庫 orm 包,簡單的 web 開發就可以開始了。

相關閱讀:

Easy way to render HTML in Go
Go 語言解析 html

image

Go 2D 圖像處理庫,支持創建 2D 處理的方法函數,圖片創建、像素、顏色設置,然後進行繪製。主要支持 png、jpeg、gif 圖片格式。

相關閱讀:

golang中image包用法
golang 中 image/draw 包用法
Golang 繪圖技術

index

目錄爲 index,其中只有一個包 index/suffixarray,稱爲後綴數組。具體算法沒仔細研究,大致是將子字符串查詢的時間複雜度降低到了 $log_n$。

使用非常簡單,官網已經提供了一個例子。

// create index for some data
index := suffixarray.New(data)

// lookup byte slice s
offsets1 := index.Lookup(s, -1) // the list of all indices where s occurs in data
offsets2 := index.Lookup(s, 3)  // the list of at most 3 indices where s occurs in data

相關閱讀:

Go package - index/suffixarray
suffix array 後綴數組算法心得

internal

內部實現,比較複雜。

io

Go 的標準庫中,爲 io 原語提供了基本的接口和實現,幫助字節流的讀取。接口主要就是 io.Reader 和 io.Writer。io 包提供了一些常用資源的接口實現,比如內存、文件和網絡連接等資源進行操作。

閱讀 io 包的源碼,會發現很多接口都是基於具體的能力定義,最簡單的有 Reader(讀)、Writer(寫)、Closer(關閉)、Seeker(偏移),一個接口一個方法,非常靈活。組合的接口還有 ReaderWriter(讀寫)、ReadeCloser(讀與關)、WriteCloser(讀寫關) 和 ReadWriteCloser(讀寫關)等。整體理解,我們將會對 Go 接口是基於是鴨子模型的說法更有體會,

相關閱讀:

Go 中 io 包的使用方法
基本的 IO 接口
Streaming IO in Go

log

Go 的日誌包,通過記錄日誌可以方便我們進行問題調試。log 包的核心源碼並不多,總共也就三百多行,其中註釋就佔了差不多一百行。主要是因爲它提供的功能很少,只有基礎的日誌格式化,還有 Print、Panic、Fatal 三種日誌打印函數。連錯誤級別沒提供。如果要使用的話,還需要藉助一些第三方的包。相關閱讀中提供了一個 "Go 日誌庫集合" 的文章,具體我也沒有深入研究。

相關閱讀:

Go log 日誌
Go 日誌庫集合

math

主要是關於數學計算方面的函數,一些數學常量,比如 PI(圓周率)、E(自然對數)等,就在其中,還有如四捨五入方面的函數 Round、Floor、Ceil、最大值 Max、最小值 Min,複雜的數學運算,比如冪運算、對數、三角函數肯定也有的,其他諸如隨機數之類的函數也在其中。打開 math 源碼文件夾,發現裏面有大量的彙編代碼,數學相對片底層,對性能要求會比較高,有必要用匯編實現。

math 包,直接看官方文檔就好了,一般看了就可以用,沒什麼業務場景、具體原理需要了解,畢竟大家都學過數學。如果要看彙編實現,那就複雜了。有興趣可以研究一下。

相關閱讀:

Go 官網 math

mime

要了解 mime 包的使用,得先了解什麼是 MIME,全稱 Multipurpose Internet Mail Extension,即多用途互聯網郵箱擴展類型。最初設計的目標是爲了在發送郵件時,附加多媒體內容。後來,MIME 在 HTML 中也得到了支持。

其中主要有四個函數,AddExtensionType、TypeByExtension、FormatMediaType 和 ParseMediaType。前後兩組函數似乎都是針對 MediaType 的互操作。

相關閱讀:

Go 標準庫學習 mime
Go package - mime

net

網絡相關,涉及內容比較多,有種吃不消的感覺。

底層的實現 socket 就在 net 包下,主要是一些底層協議的實現,比如無連接的 ip、udp、unix(DGRAM),和有連接的 tcp、unix(STREAM) 都可以在 net 包找到。

應用層協議,http 協議實現在 net/http 包含客戶端服務端,rpc 在 net/rpc,郵件相關的 net/mail、net/smtp 等。net/url 是與 url 處理相關的函數,比如 url 字符串解析,編碼等。

相關閱讀:

golang net 包學習筆記
Go 官方庫 RPC 開發指南
Go 爬蟲必備之 HTTP 請求 QuickStart
Sending HTML emails using templates in Golang

os

os 包主要實現與操作系統相關的函數,並且是與平臺無關的。它的設計是 UNIX 風格的,並且採用 Go 錯誤處理風格。發生錯誤將返回的 error 類型變量。比如 Open、Stat 等操作相關的函數。

os 包的目標是統一不同操作系統的函數。如果大家讀過那本 UNIX 環境高級編程,你會發現 os 包中的函數與 Unix 的系統調用函數都很相似。

除了 os 包,該目錄下還有幾個包,分別是 os/exec、os/signal 和 os/user,如下:

os/exec,幫助我們實現了方便執行外部命令的能力。

os/signal,Unix-Like 的系統信號處理相關函數,Linux 支持 64 中系統信號。

os/user,與系統用戶相關的庫,可用於獲取登錄用戶、所在組等信息。

相關閱讀:

[[譯]使用 os/exec 執行命令](https://colobu.com/2017/06/19...
Go package - os

path

path 包實現了路徑處理(通過 / 分隔)相關的一些常用函數,常用於如文件路徑、url 的 path。不適合 Windows 的 和磁盤路徑處理。

主要包含的函數有 Base、Clean、Dir、Ext、IsAbs、Join 等函數。如 Base 可用於獲取路徑的最後一個元素,Dir 獲取路徑目錄,Ext 獲取文件擴展、IsAbs 判斷是否爲絕對路徑,Join 進行路徑連接等。

相關閱讀:

Go package - path

plugin

plugin 包是 Go 1.8 出現的包,爲 Go 增加了動態庫加載的能力,當前只支持 Linux 和 MacOS。但這個包的應用並不是很方便,生成和使用庫文件的環境有一定的要求。

相關閱讀:

如何評價 Go 標準庫中新增的 plugin 包
writing-modular-go-programs-with-plugins
calling-go-functions-from-other-languages
gosh-a-pluggable-command-shell-in-go

reflect

與反射相關的函數函數,通過反射可以實現運行時動態創建、修改變量,進行函數方法的調用等操作,獲得本屬於解釋語言的動態特性。要閱讀反射包源碼,重點在理解變量的兩個組成,即類型和值,反射的核心操作基本都是圍繞它們進行。reflect.ValueOf 與 reflect.TypeOf 是我們常用的兩個方法。

相關閱讀:

Go 譯文之如何使用反射
Go 譯文之如何使用反射(二)
Go package - reflect

regexp

Go 的正則包,用於正則處理。基本是每種語言都會提供。其中涉及的方法大致可分爲幾個大類,分別是 Compile 編譯、Match 匹配、Find 搜索、Replace 替換。

正則的源碼實現還真是不想看。感覺正則都沒有完全理清楚,扯源碼有點坑。特別頭大。

相關閱讀:

Go 官網之 regexp
Golang-Regex-Tutorial

runtime

runtime 是與 Go 運行時相關的實現,我們可以通過它提供的一些函數控制 goroutine。關於 Go 進程的啓動流程、GC、goroutine 調度器等,也是在 runtime 中實現,同樣需要我們好好閱讀 runtime 代碼瞭解。除此以爲,cgo、builtin 包的實現也是在 runtime。

相關閱讀:

說說 Golang 的runtime
golang internals
Go package - runtime

sort

定義了排序的接口,一旦某個類型實現了排序的接口,就可以利用 sort 中的函數實現排序。通過閱讀源碼,我發現默認支持排序的類型包括 int、float64、string。sort 中還有個 search 文件,其中主要是已排序內容二分查找的實現。

我們都知道,排序算法很多,比如插入排序、堆排序與快速排序等,sort 包都已經實現了,並且不用我們決定使用哪種算法,而是會依據具體的數據決定使用什麼算法,並且一次排序不一定只要了一種算法,而可能是多種算法的組合。如何做算法選擇可以通過閱讀 sort.go 文件中的 quickSort 函數了解。

相關閱讀:

Sort - 排序算法
The 3 ways to sort in Go

strconv

關於字符串與其他類型轉化的包,名字全稱應該是 string convert,即字符串轉化。比如整型與字符串轉化的 Itoa 與 Atoi,浮點型與字符串的轉化 ParseFloat 與 FormatFloat,布爾型與字符串轉化 ParseBool 與 FormatBool 等等。

相關閱讀:

Golang 中 strconv 的用法
官方文檔 - strconv

strings

針對字符串的操作函數,前面也提過到,因爲 []byte 也可用於表示字符串,strings 中的很多函數在 bytes 包也有類似的實現,比如 Join、Split、Trim,大小寫轉化之類的函數等。

相關閱讀:

strings - 字符串操作

sync

Go 推薦以通信方式(channel)實現併發同步控制,但傳統機制也是支持的,比如鎖機制、條件變量、WaitGroup、原子操作等,而它們都是由 sync 提供的。其中,原子操作在 sync/atomic 包下。

除此之外,sync 中還有個臨時對象池,可以實現對象複用,並且它是可伸縮且併發安全的。

相關閱讀:

淺談 Golang sync 包的相關使用方法

syscall

系統調用,從名字就能知道,這個包很複雜。系統調用是實現應用層和操作底層的接口,不同系統之間的操作常常會有一定的差異,特別是類 Unix 與 Windows 系統之間的差異較大。

如果想要尋找 syscall 的使用案例,我們可以看看 net、os、time 這些包的源碼。

如果要看這部分源碼,當前的想法是,我們可以只看 Linux 的實現,架構的話,如果想看彙編,可以只看 x86 架構。

暫時研究不多,不敢妄言。

相關閱讀:

視頻筆記:Go 和 syscall
[Go package - syscall]()

testing

Go 中測試相關的實現,比如單元測試、基準測試等。Go 推薦的測試方式採用表格驅動的測試方式,即非每種情況都要寫一個單獨的用例,而是通過列舉輸入、期望輸出,然後執行功能並比較期望輸出與實際輸出是否相同。

一個簡單的測試用例。

func TestSum(t *testing.T) {
    var sumTests = []struct {
        a        int
        b        int
        expected int
    }{
        {1, 1, 2},
        {2, 1, 3},
        {3, 2, 5},
        {4, 3, 7},
        {5, 5, 10},
        {6, 8, 14},
        {7, 13, 20},
    }

    for _, tt := range sumTests {
        actual := functions.Add(tt.a, tt.b)
        if actual != tt.expected {
            t.Errorf("Add(%d, %d) = %d; expected %d", tt.a, tt.b, actual, tt.expected)
        }
    }
}

相關閱讀:

單元測試
基準測試
Go package - testing

text

主要是關於文本分析解析的一些包,但又不同於字符串處理,主要涉及詞法分析 scanner、模板引擎 template、tab 處理 tabwriter。

text/scanner,主要是做詞法分析的,如果大家讀過我的專欄翻譯的幾篇關於詞法分析的文章,對它的理解會比較輕鬆。

text/template,用於文本的模板處理,相對於 html/template 的具體應用場景,text/template 更通用。要熟悉使用它,還需要掌握它的一些方法,比如 Action、Argument、Pipeline、Variable、Function。

text/tabwriter,感覺沒啥介紹的,好像主要是根據 tab 進行文本對齊的。

相關閱讀:

text/template
A look at Go lexer/scanner packages
Go 模板嵌套最佳實踐
Package tabwriter

time

關於日期時間的包,Go 中的 unix timestamp 是 int64,表示的時間範圍相應的也就有所擴大。其他的諸如睡眠、時區、定時控制等等都支持,Go 中有個逆人性的規則,那就是日期時間的格式化字符,比如傳統語言的格式化字符串 YYYY-MM-DD 在 Go 卻是 2006-01-02 的形式,奇葩不奇葩。

相關閱讀:

Go 標準庫--time 常用類型和方法
Go 時間、時區、格式的使用
golang package time 用法詳解

unicode

unicode 編碼相關的一些基本函數,讀源碼會發現,它通過把不同分類字符分別到不同的 RangeTable 中,實現提供函數判斷字符類型,比如是否是控制字符、是否是字母等。另外兩個包 unicode/utf8 和 unicode/utf16 可用於 unicode (rune) 與 utf8 (byte)、unicode (rune) 與 utf16 (int16) 之間的轉化。

相關閱讀:

go package 之 unicode
Unicode 碼點、UTF-8/16編碼

unsafe

Go 語言限制了一些可能導致程序運行出錯的用法,通過編譯器就可以檢查出這些問題。當然,也有部分問題是無法在編譯時發現的,Go 給了比較優化的提示。但通過 unsafe 中提供的一些方法,我們可以完全突破這一層限制,從包名就可以知道,unsafe 中包含了一些不安全的操作,更加偏向於底層。一些比較低級的包會調用它,比如 runtime、os、syscall 等,它們都是和操作系統密切相關的。我們最好少用 unsafe,因爲使用了它就不一定能保證程序的可移植性或未來的兼容性問題。

相關閱讀:

Go 聖經 - 底層編程
Go package - unsafe

vendor

標準庫中依賴的第三方包,當然也都由 Go 官方所開發,默認包括的依賴有:

  • golang_org/x/crypto
  • golang_org/x/net
  • golang_org/x/text

舉個例子,加密相關的 crypto 包中實現就用到了 golang_org/x/crypto/curve25519 中的方法。

除了源碼中自帶的標準庫,官方其實還提供了其他很多諸如 crypto、net、text 之類的包。具體可以查看 Go 官方 github 地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章