Go語言規範2 - 命名篇

命名篇

本篇以開發時從上往下的順序既:開發前約定的基本命名規範、包、常量、變量、結構體、參數、返回值的順序講解了開發中各個環節的命名規範。

2.1 基本命令規範

【規則2.1.1】需要註釋來補充的命名就不算是好命名。

說明:命名應該做到讓人見名知意,好的命名可以讓人節省關注註釋的時間。

【規則2.1.2】使用可搜索的名稱

說明:單字母名稱和數字常量很難從一大堆文字中搜索出來。單字母名稱僅適用於短方法中的本地變量,名稱長短應與其作用域相對應。若變量或常量可能在代碼中多處使用,則應賦其以便於搜索的名稱。

【規則2.1.3】做有意義的區分

說明:要區分名稱,就要以讀者能鑑別不同之處的方式來區分

比如說Product 和 ProductInfo 和 ProductData 沒有區別,NameString 和 Name 沒有區別。

錯誤示例:

 type Reader interface {
        Read(p []byte) (n int, err error)
  }

  // 多個函數接口
  type WriteFlusher interface {
      Write([]byte) (int, error)
      Flush() error
  }

2.2 項目目錄名

【規則2.2.1】目錄名必須爲全小寫單詞,允許加中劃線‘-’組合方式,但是頭尾不能爲中劃線。

例如:

go-sql-driver
hsa-microservice
service-mgr

【建議2.2.2】雖然允許出現中劃線,但是儘量避免或少加中劃線。

2.3 包名

【原則2.3.1】取名儘量採取有意義的包名,簡單和可閱讀。

【規則2.3.2】包名必須全部爲小寫單詞,無下劃線,越短越好。儘量不要與標準庫重名。

錯誤示例:

import (

    "MyUtil"                //包名大寫          

    "suffix_array"          //有下劃線
    
    "io/util suffixarray"   //不僅長,還是個帶空格的包名
    
    "io/ioutil"             //與標準庫重名
    
)

說明:包名在被導入後,會以 package.Func()方式使用,任何人使用你的包都得敲一遍該包名,因爲包名也是類型和函數的一部分

例如buf := new(bytes.Buffer)就不要取名爲 bytes.BytesBuffer,這樣過於累贅。

【規則2.3.3】禁止通過中劃線連接多個單詞的方式來命名包名。

package go-oci8 //編譯錯誤

【建議2.3.4】包名儘量與所在目錄名一致,引用時比較方便。

說明:這是因爲在import導入的包是按目錄名來命名的,如果不一致,代碼閱讀者就很困惑。

2.4 文件名

和其它語言一樣,名字在Go中是非常重要的。它們甚至還具有語義的效果:一個名字在程序包之外的可見性是由它的首字符是否爲大寫來確定的。因此,值得花費一些時間來討論Go程序中的命名約定。

【規則2.4.1】文件名必須爲小寫單詞,允許加下劃線‘_’組合方式,但是頭尾不能爲下劃線。

例如: port_allocator.go

【建議2.4.2】雖然允許出現下劃線,但是儘量避免。

說明:如果採用下劃線的方式,注意避免跟下面保留特定用法的後綴衝突: 
1)測試文件:_test.go
2)系統相關的文件:

_386.go、_amd64.go、_arm.go、_arm64.go、_android.go、_darwin.go、_dragonfly.go、_freebsd.go、_linux.go、_nacl.go、_netbsd.go、_openbsd.go、_plan9.go、_solaris.go、_windows.go、_android_386.go、_android_amd64.go、_android_arm.go、_android_arm64.go、_darwin_386.go、_darwin_amd64.go、_darwin_arm.go、_darwin_arm64.go、_dragonfly_amd64.go、_freebsd_386.go、_freebsd_amd64.go、_freebsd_arm.go、_linux_386.go、_linux_amd64.go、_linux_arm.go、_linux_arm64.go、_linux_mips64.go、_linux_mips64le.go、_linux_ppc64.go、_linux_ppc64le.go、_linux_s390x.go、_nacl_386.go、_nacl_amd64p32.go、_nacl_arm.go、_netbsd_386.go、_netbsd_amd64.go、_netbsd_arm.go、_openbsd_386.go、_openbsd_amd64.go、_openbsd_arm.go、_plan9_386.go、_plan9_amd64.go、_plan9_arm.go、_solaris_amd64.go、_windows_386.go
_windows_amd64.go

【建議2.4.3】文件名以功能爲指引,名字中不需再出現模塊名或者組件名。

說明:因爲Go包的導入是與路徑有關的,本身已經隱含了模塊/組件信息。

2.5 常量

【規則2.5.1】常量&枚舉名採用大小寫混排的駝峯模式(Golang官方要求),不允許出現下劃線

示例:

    const (
        CategoryBooks    = iota // 0
        CategoryHealth          // 1
        CategoryClothing        // 2
    )

【建議2.5.2】按照功能來區分,而不是將所有類型都分在一組,並建議將公共常量置於私有常量之前

示例:

    const (
        KindPage = "page"
    
        // The rest are node types; home page, sections etc.
        KindHome         = "home"
        KindSection      = "section"
        KindTaxonomy     = "taxonomy"
        KindTaxonomyTerm = "taxonomyTerm"
    
        // Temporary state.
        kindUnknown = "unknown"
    
        // The following are (currently) temporary nodes,
        // i.e. nodes we create just to render in isolation.
        kindRSS       = "RSS"
        kindSitemap   = "sitemap"
        kindRobotsTXT = "robotsTXT"
        kind404       = "404"
    )

【規則2.2.3】如果是枚舉類型的常量,需要先創建相應類型

示例:

    type tstCompareType int
    
    const (
        tstEq tstCompareType = iota
        tstNe
        tstGt
        tstGe
        tstLt
        tstLe
    )

【建議2.5.4】如果模塊的功能較爲複雜、常量名稱容易混淆的情況下,爲了更好地區分枚舉類型,可以使用完整的前綴

示例:

    type PullRequestStatus int
    
    const (
        PullRequestStatusConflict PullRequestStatus = iota
        PullRequestStatusChecking
        PullRequestStatusMergeable
    )

2.6 變量

變量申明

【規則2.6.1】變量命名基本上遵循相應的英文表達或簡寫,在相對簡單的環境(對象數量少、針對性強)中,可以將一些名稱由完整單詞簡寫爲單個字母

例如:

  • user 可以簡寫爲 u
  • userID 可以簡寫 uid
  • 若變量類型爲 bool 類型,則名稱應以 Has, Is, Can 或 Allow 開頭:
  var isExist bool
  var hasConflict bool
  var canManage bool
  var allowGitHook bool
  

只有從其他標準移植過來的常量才和原來保持一致,比如:

  • 自定義的 http.StatusOK

  • 移植過來的 tls.TLS_RSA_WITH_AES_128_CBC_SHA

變量命名慣例

【規則2.6.2】變量名稱一般遵循駝峯法,並且不允許出現下劃線,當遇到特有名詞時,需要遵循以下規則:

  • 如果變量爲私有,且特有名詞爲首個單詞,則使用小寫,如:apiClient
  • 其它情況都應當使用該名詞原有的寫法,如 APIClient、repoID、UserID

錯誤示例:UrlArray,應該寫成 urlArray 或者 URLArray

下面列舉了一些常見的特有名詞:

"API","ASCII","CPU","CSS","DNS","EOF",GUID","HTML","HTTP","HTTPS","ID","IP","JSON","LHS","QPS","RAM","RHS"
  "RPC", "SLA","SMTP","SSH","TLS","TTL","UI","UID","UUID","URI","URL", "UTF8","VM","XML","XSRF","XSS"

【規則2.6.3】不要使用_來命名變量名,多個變量申明放在一起

正確示例:

var (
    Found bool
    count int
)

【規則2.6.4】在函數外部申明必須使用var,不要採用:=,容易踩到變量的作用域的問題。

全局變量名

【規則2.6.5】全局變量必須爲大小寫混排的駝峯模式,不允許出現下劃線。首字母根據作爲範圍確定大小寫。

例如:

    var Global int //包外
    var global int //包內

【建議2.6.6】儘量避免跨package使用全局變量,儘量減少全局變量的使用。

局部變量名

【規則2.6.7】局部變量名必須爲大小寫混排,且首字母小寫,不能有下劃線。
例如:

    result, err := MakeRegexpArray(str)

循環變量

【建議2.6.8】for循環變量可以使用單字母。

2.7 結構體(struct)

【規則2.7.1】struct申明和初始化格式採用多行

定義如下:

type User struct{
    Username  string
    Email     string
}

初始化如下:

u := User{
    Username: "astaxie",
    Email:    "[email protected]",
}

【規則2.7.2】結構體名必須爲大小寫混排的駝峯模式,不允許出現下劃線,可被包外部引用則首字母大寫;如僅包內使用,則首字母小寫。

例如:

    type ServicePlan struct 
    type internalBroker struct

【建議2.7.3】結構名建議採用名詞、動名詞爲好。

結構體名應該是名詞或名詞短語,如Custome、WikiPage、Account、AddressParser,避免使用 Manager、Processor、Data、Info、這樣的類名,類名不應當是動詞。

2.8 接口名

接口命名規則:單個函數的接口名以”er”作爲後綴,

【規則2.8.1】接口名必須爲大小寫混排,支持包外引用則首字母大寫,僅包內使用則首字母小寫。不能有下劃線,整體必須爲名詞。

【建議2.8.2】單個函數的接口名以”er”作爲後綴。

單個函數的接口名以”er”作爲後綴,如Reader,Writer。接口的實現則去掉“er”。除非有更合適的單詞。

例如:

    type Reader interface {...}

2.9 函數和方法名

函數

【規則2.9.1】函數名必須爲大小寫混排的駝峯模式

函數名必須爲大小寫混排的駝峯模式,名字可以長但是得把功能,必要的參數描述清楚,不允許出現下劃線。

示例:

func MakeRegexpArrayOrDie     // 暴露給包外部函數

func matchesRegexp            // 包內部函數

【建議2.9.2】函數名力求精簡準確,並採用用動詞或動詞短

如 postPayment、deletePage、save。並依 Javabean 標準加上 get、set、is前綴。

例如:xxx + With + 需要的參數名 + And + 需要的參數名 + …..

方法

【規則2.9.3】方法接收名必須爲大小寫混排,首字母小寫。方法接收者命名要能夠體現接收者對象。

【建議2.9.4】接收者名通常1個或者2個字母就夠,最長不能超過4個字母。

【建議2.9.5】接收者名不要使用me,this 或者 self 這種泛指的名字。

例如:

    func (c *Controller) Run(stopCh <-chan struct{})

參考:https://github.com/golang/go/wiki/CodeReviewComments#receiver-names

【建議2.9.6】定義方法時,如果方法內不會直接引用接收者,則省略掉接收者名。

舉例:

func (T) sayHi() {
    // do things without T
}

func (*T) sayHello() {
    // do things without *T
}

2.10 參數名

【規則2.10】參數名必須爲大小寫混排,且首字母小寫,不能有下劃線。

例如:

    func MakeRegexpArray(str string)

2.11 返回值

【規則2.11.1】返回值如果是命名的,則必須大小寫混排,首字母小寫。

【建議2.11.2】 函數的返回值應避免使用命名的參數。

舉例:

    func (n *Node) Bad() (node *Node, err error)
    func (n *Node) Good() (*Node, error)

因爲如果使用命名變量很容易導致臨時變量覆蓋而引起隱藏的bug。

例外情況:多個返回值類型相同的情況下,使用命名返回值來區分不同的返回參數。

說明:命名返回值使代碼更清晰,同時更加容易讀懂。

舉例:

func getName()(firstName, lastName, nickName string){
    firstName = "May"
    lastName = "Chen"
    nickName = "Babe"
    return
}

參考:
https://github.com/golang/go/wiki/CodeReviewComments#named-result-parameters
https://golang.org/doc/effective_go.html#named-results

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