Go 包和命名
針對 package 和其成員的命名,本節會提供一些建議,使其與 Go 特有慣例相符。
1. package 的命名
先說創建、命名 package 時的注意事項:
-
保持名字短小,但不能太過簡單短,以至於晦澀難懂。
標準包中最常用的被命名爲 bufio, bytes, flag, fmt, http, io, json, os, sort, sync, time 。
-
名字要做清晰描述,杜絕通用含糊。
舉例來說,工具包不要命名爲 util ,要使用更明確,同時不失簡潔的名字:imageutil 或 ioutil 。
-
package 名字,避開常用的變量名。
否則你就是在強迫使用者使用 renaming imports ,就像 path 包
-
包名稱採用單數形式。
只有少數例外,纔會採用複數形式,一種以 bytes, errors, strings 爲代表, 目的是避開 Go 內置類型名稱,另一種以 go/types 爲代表,目的是避開對應的 Go 保留關鍵字。
-
避免會引發誤解的名字
舉例來說,2.5 節中溫度轉換包,我們開始叫 temp ,但沒多久,我們就意識到這名字很糟,因爲 temp 一般用於表示 temporary 。我們又改爲 temperature ,但也沒過多久,我們發現它又長,又不能說明它的作用。最終使用的名字是 tempconv ,它既短小,又和 strconv 這樣的名字一致。
2. package 內部成員的命名
現在說說包內部成員的命名。
因爲編碼時,引用另一個包中的成員,要使用全名,比如 fmt.Println,因此描述成員,等同於包的名稱加上成員的名稱。
你可能已經發現用於格式化的函數 Println ,其函數名中並不提及 “格式化”,這是因爲該含義由包名達成。
這就是說,當設計一個 package 時,不能只關注成員命名,要意識到全名是由 2 個部分組成的,重點關注它倆組合後的整體效果 ?
下面是一些典型例子:
bytes.Equal
flag.Int
http.Get
json.Marshal
該如何借鑑一些已有的優秀命名模式 ?以 strings 包提供的一組彼此獨立的字符串操作函數爲例
package strings
func Index(needle, haystack string) int
type Replacer struct{ /* ... */ }
func NewReplacer(oldnew ...string) *Replacer
type Reader struct{ /* ... */ }
func NewReader(s string) *Reader
字符串 string 不會在其中的任何一個函數名稱中出現。而使用者是通過 strings.Index, strings.Replacer 實現這些函數的引用。
3. 其他情況下的命名
除此之外,還有一些包,我們稱爲 single-type packages 。
比如 html/template 或是 math/rand ,它們會暴露一個主要的類型以及該類型的各種方法,還有一個 New 函數用來創建類型的實例。
package rand // "math/rand"
type Rand struct{ /* ... */ }
func New(source Source) *Rand
這些名字引用時一定會導致同義反復 (重複),比如 template.Template 或 rand.Rand , 這就是爲什麼這類包的名字要取得特別短的原因。
最後還有一類特殊的情況。
那就是類似 net/http 這樣的包,包內含有一堆的成員名,但並沒有特定結構,這通常是因爲這些包完成的任務太過複雜,與此同時,包內也許會含有一沓子各種類型,以及數量更多的函數。
要注意的是,包中最重要的成員的名字,應該是最簡單的,比如 Get, Post, Handle, Error, Client, Server 。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/apgIgsmuQkw5gCKdqUHfhQ