Golang編碼規(guī)范

  • gofmt

大部分的格式問題可以通過gofmt解決,gofmt自動格式化代碼,保證所有的go代碼與官方推薦的格式保持一致,于是所有格式有關(guān)問題,都以gofmt的結(jié)果為準(zhǔn)。

  • 行長

一行最長不超過80個字符,超過的使用換行展示,盡量保持格式優(yōu)雅。

  • 注釋

在編碼階段應(yīng)該同步寫好變量、函數(shù)、包的注釋,最后可以利用godoc導(dǎo)出文檔。注釋必須是完整的句子,句子的結(jié)尾應(yīng)該用句號作為結(jié)尾(英文句號)。注釋推薦用英文,可以在寫代碼過程中鍛煉英文的閱讀和書寫能力。而且用英文不會出現(xiàn)各種編碼的問題。
每個包都應(yīng)該有一個包注釋,一個位于package子句之前的塊注釋或行注釋。包如果有多個go文件,只需要出現(xiàn)在一個go文件中即可。

// ping包實現(xiàn)了常用的ping相關(guān)的函數(shù)
package ping

導(dǎo)出函數(shù)注釋,第一條語句應(yīng)該為一條概括語句,并且使用被聲明的名字作為開頭。

// 求a和b的和,返回sum。
func Myfunction(sum int) (a, b int) {
  • 命名

    • 需要注釋來補充的命名就不算是好命名。
    • 使用可搜索的名稱:單字母名稱和數(shù)字常量很難從一大堆文字中搜索出來。單字母名稱僅適用于短方法中的本地變量,名稱長短應(yīng)與其作用域相對應(yīng)。若變量或常量可能在代碼中多處使用,則應(yīng)賦其以便于搜索的名稱。
    • 做有意義的區(qū)分:Product和ProductInfo和ProductData沒有區(qū)別,NameString和Name沒有區(qū)別,要區(qū)分名稱,就要以讀者能鑒別不同之處的方式來區(qū)分 。
    • 函數(shù)命名規(guī)則:駝峰式命名,名字可以長但是得把功能,必要的參數(shù)描述清楚,函數(shù)名名應(yīng)當(dāng)是動詞或動詞短語,如postPayment、deletePage、save。并依Javabean標(biāo)準(zhǔn)加上get、set、is前綴。例如:xxx + With + 需要的參數(shù)名 + And + 需要的參數(shù)名 + .....
    • 結(jié)構(gòu)體命名規(guī)則:結(jié)構(gòu)體名應(yīng)該是名詞或名詞短語,如Custome、WikiPage、Account、AddressParser,避免使用Manager、Processor、Data、Info、這樣的類名,類名不應(yīng)當(dāng)是動詞。
    • 包名命名規(guī)則:包名應(yīng)該為小寫單詞,不要使用下劃線或者混合大小寫。
    • 接口命名規(guī)則:單個函數(shù)的接口名以"er"作為后綴,如Reader,Writer。接口的實現(xiàn)則去掉“er”。
type Reader interface {
        Read(p []byte) (n int, err error)
}

兩個函數(shù)的接口名綜合兩個函數(shù)名

type WriteFlusher interface {
    Write([]byte) (int, error)
    Flush() error
}

三個以上函數(shù)的接口名,抽象這個接口的功能,類似于結(jié)構(gòu)體名

type Car interface {
    Start([]byte)
    Stop() error
    Recover()
}
  • 常量

常量均需使用全部大寫字母組成,并使用下劃線分詞:

const APP_VER = "1.0"

如果是枚舉類型的常量,需要先創(chuàng)建相應(yīng)類型:

type Scheme string

const (
    HTTP  Scheme = "http"
    HTTPS Scheme = "https"
)

如果模塊的功能較為復(fù)雜、常量名稱容易混淆的情況下,為了更好地區(qū)分枚舉類型,可以使用完整的前綴:

type PullRequestStatus int

const (
    PULL_REQUEST_STATUS_CONFLICT PullRequestStatus = iota
    PULL_REQUEST_STATUS_CHECKING
    PULL_REQUEST_STATUS_MERGEABLE
)
  • 變量

變量命名基本上遵循相應(yīng)的英文表達或簡寫,在相對簡單的環(huán)境(對象數(shù)量少、針對性強)中,可以將一些名稱由完整單詞簡寫為單個字母,例如:
* user 可以簡寫為 u
* userID 可以簡寫 uid
若變量類型為 bool 類型,則名稱應(yīng)以 Has, Is, Can 或 Allow 開頭:

var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool
  • 變量命名慣例

變量名稱一般遵循駝峰法,但遇到特有名詞時,需要遵循以下規(guī)則:

* 如果變量為私有,且特有名詞為首個單詞,則使用小寫,如 apiClient
* 其它情況都應(yīng)當(dāng)使用該名詞原有的寫法,如 APIClient、repoID、UserID
* 錯誤示例:UrlArray,應(yīng)該寫成urlArray或者URLArray

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

// A GonicMapper that contains a list of common initialisms taken from golang/lint
var LintGonicMapper = GonicMapper{
    "API":   true,
    "ASCII": true,
    "CPU":   true,
    "CSS":   true,
    "DNS":   true,
    "EOF":   true,
    "GUID":  true,
    "HTML":  true,
    "HTTP":  true,
    "HTTPS": true,
    "ID":    true,
    "IP":    true,
    "JSON":  true,
    "LHS":   true,
    "QPS":   true,
    "RAM":   true,
    "RHS":   true,
    "RPC":   true,
    "SLA":   true,
    "SMTP":  true,
    "SSH":   true,
    "TLS":   true,
    "TTL":   true,
    "UI":    true,
    "UID":   true,
    "UUID":  true,
    "URI":   true,
    "URL":   true,
    "UTF8":  true,
    "VM":    true,
    "XML":   true,
    "XSRF":  true,
    "XSS":   true,
}
  • struct規(guī)范

struct申明和初始化格式采用多行:

定義如下:

type User struct{
    Username  string
    Email     string
}

初始化如下:

u := User{
    Username: "test",
    Email:    "test@gmail.com",
}
  • 控制結(jié)構(gòu)

if
if接受初始化語句,約定如下方式建立局部變量

if err := file.Chmod(0664); err != nil {
    return err
}

for
采用短聲明建立局部變量

sum := 0
for i := 0; i < 10; i++ {
    sum += i
}

return
盡早return:一旦有錯誤發(fā)生,馬上返回

f, err := os.Open(name)
if err != nil {
    return err
}
d, err := f.Stat()
if err != nil {
    f.Close()
    return err
}
codeUsing(f, d)
  • 錯誤處理

    • error作為函數(shù)的值返回,必須對error進行處理
    • 錯誤描述如果是英文必須為小寫,不需要標(biāo)點結(jié)尾
    • 采用獨立的錯誤流進行處理

不要采用下面的處理錯誤寫法

    if err != nil {
        // error handling
    } else {
        // normal code
    }

采用下面的寫法

    if err != nil {
        // error handling
        return // or continue, etc.
    }
    // normal code

使用函數(shù)的返回值時,則采用下面的方式

x, err := f()
if err != nil {
    // error handling
    return
}
// use x
  • panic

盡量不要使用panic,除非你知道你在做什么

  • import

對import的包進行分組管理,用換行符分割,而且標(biāo)準(zhǔn)庫作為分組的第一組。如果你的包引入了三種類型的包,標(biāo)準(zhǔn)庫包,程序內(nèi)部包,第三方包,建議采用如下方式進行組織你的包

package main

import (
    "fmt"
    "os"

    "kmg/a"
    "kmg/b"

    "code.google.com/a"
    "github.com/b"
)

在項目中不要使用相對路徑引入包:

// 錯誤示例
import “../net”

// 正確的做法
import “github.com/repo/proj/src/net”

goimports會自動幫你格式化

  • 參數(shù)傳遞

    • 對于少量數(shù)據(jù),不要傳遞指針
    • 對于大量數(shù)據(jù)的struct可以考慮使用指針
    • 傳入?yún)?shù)是map,slice,chan不要傳遞指針,因為map,slice,chan是引用類型,不需要傳遞指針的指針
  • 單元測試

單元測試文件名命名規(guī)范為 example_test.go
測試用例的函數(shù)名稱必須以 Test 開頭,例如:TestExample



歡迎關(guān)注我的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容