前言
本篇主要講述Go語(yǔ)言的命名規(guī)范。優(yōu)秀的代碼必須具備良好的可讀性,而可讀性的關(guān)鍵即在于命名風(fēng)格。
Go的函數(shù)、變量、常量、自定義類型、包(Package)的命名方式遵循以下規(guī)則:
1)首字符可以是任意的Unicode字符或者下劃線
2)剩余字符可以是Unicode字符、下劃線、數(shù)字
3)字符長(zhǎng)度不限
Go只有25個(gè)關(guān)鍵字
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
優(yōu)秀的命名
- 優(yōu)秀的命名應(yīng)當(dāng)是一貫的、短小的、精確的。
- 所謂一貫,就是說(shuō)同一個(gè)意義在不同的環(huán)境下的命名應(yīng)當(dāng)一致,譬如依賴關(guān)系,不要在一個(gè)方法中命名為depend,另一個(gè)方法中命名為rely。
- 所謂短小,不必多言,當(dāng)命名過(guò)長(zhǎng)的時(shí)候,讀者可能更關(guān)注命名本身,而忽視真正的邏輯內(nèi)容。
- 所謂精確,就是命名達(dá)意、易于理解
首條經(jīng)驗(yàn)
聲明位置與使用位置越遠(yuǎn),則命名應(yīng)當(dāng)越長(zhǎng)。
駱駝命名法
- Go語(yǔ)言應(yīng)該使用 MixedCase
- (不要使用 names_with_underscores)
- 首字母縮寫詞都應(yīng)該用大寫,譬如ServeHTTP、sceneID、CIDRProcessor。
局部變量
- 局部變量應(yīng)當(dāng)盡可能短小,譬如使用buf指代buffer,使用i指代index
- 在很長(zhǎng)的函數(shù)中可能會(huì)有很多的變量,這個(gè)時(shí)候可以適當(dāng)使用一些長(zhǎng)名字。
- 但是寫出這么長(zhǎng)的函數(shù),通常意味著代碼需要重構(gòu)了!🙅🏻
參數(shù)
函數(shù)的參數(shù)和局部變量類似,但是它們默認(rèn)還具有文檔的功能
當(dāng)參數(shù)類型具有描述性的時(shí)候,參數(shù)名就應(yīng)該盡可能短?。?/p>
func AfterFunc(d Duration, f func()) *Timer
func Escape(w io.Writer, s []byte)
當(dāng)參數(shù)類型比較模糊的時(shí)候,參數(shù)名就應(yīng)當(dāng)具有文檔的功能:
func Unix(sec, nsec int64) Time
func HasPrefix(s, prefix []byte) bool
返回值
在Go語(yǔ)言中,返回值可以定義名稱的,它可以當(dāng)做一種特殊的參數(shù)。
尤其重要的是,在外部可見的函數(shù)中,返回值的名稱應(yīng)當(dāng)可以作為文檔參考。
func Copy(dst Writer, src Reader) (written int64, err error)
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte,
err error)
方法接收者(Receiver)
方法接收者也是一種特殊的參數(shù)。Go語(yǔ)言中沒(méi)有明顯的面向?qū)ο蟮母拍?,可以?duì)方法定義方法接收者來(lái)實(shí)現(xiàn)類似于對(duì)象的方法的概念。
按照慣例,由于方法接收者在函數(shù)內(nèi)部經(jīng)常出現(xiàn),因此它經(jīng)常采用一兩個(gè)字母來(lái)標(biāo)識(shí)方法接收者的類型。
func (b *Buffer) Read(p []byte) (n int, err error)
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request)
func (r Rectangle) Size() Point
需要注意的是,方法接收者的名字在同一類型的不同方法中應(yīng)該保持統(tǒng)一,這也是前文所述的一貫性的需求。
導(dǎo)出包級(jí)別命名
導(dǎo)出名被使用的時(shí)候通常是放在包名后
所以,在導(dǎo)出變量、常數(shù)、函數(shù)和類型的時(shí)候,
不要把包名的意義再寫一遍
比較好的名字
bytes.Buffer strings.Reader
比較蠢的名字
bytes.ByteBuffer strings.StringReader
接口類型
只含有一個(gè)方法的接口類型通常以函數(shù)名加上er后綴作為名字
type Reader interface {
Read(p []byte) (n int, err error)
}
有時(shí)候可能導(dǎo)致蹩腳的英文,但別管他,能看懂就好
type Execer interface {
Exec(p []byte) (n int, err error)
}
有時(shí)候可以適當(dāng)調(diào)整一下英文單詞的順序,增加可讀性:
type ByteReader interface {
ReadByte(p []byte) (n int, err error)
}
當(dāng)接口含有多個(gè)方法的時(shí)候,還是要選取一個(gè)能夠精準(zhǔn)描述接口目的的名字,譬如net.Conn、http/ResponseWriter
Error的命名
Error類型應(yīng)該寫成FooError的形式
type ExitError struct {
....
}
Error變量協(xié)程ErrFoo的形式
var ErrFormat = errors.New("unknown format")
包的命名
應(yīng)當(dāng)與它導(dǎo)出代碼的內(nèi)容相關(guān),避免util、common這種寬泛的命名
引入路徑
包路徑的最后一個(gè)單詞應(yīng)該和包名一致
包路徑應(yīng)該盡可能簡(jiǎn)潔
記得把庫(kù)的主要代碼直接放在代碼庫(kù)的根目錄
避免在包路徑中使用任何大寫字母(并非所有文件系統(tǒng)都區(qū)分大小寫)
標(biāo)準(zhǔn)庫(kù)
上述很多例子都是從標(biāo)準(zhǔn)庫(kù)中來(lái)的
標(biāo)準(zhǔn)庫(kù)的很多內(nèi)容都可以作為參考
多看看標(biāo)準(zhǔn)庫(kù)來(lái)尋求靈感吧
但是要記?。?/p>
當(dāng)作者寫標(biāo)準(zhǔn)庫(kù)的時(shí)候,他們自己也在學(xué)習(xí)過(guò)程中。
多數(shù)情況下作者是對(duì)的,但是偶爾還是會(huì)犯一些錯(cuò)誤
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
參考文獻(xiàn)
What's in a name? - Andrew Gerrand