1. 程式人生 > 其它 >[轉]Go編碼規範

[轉]Go編碼規範

原地址:
https://github.com/rubyhan1314/Golang-100-Days/blob/master/Day01-15(Go語言基礎)/day01_第11節 _編碼規範.md

編碼規範

@author:韓茹
版權所有:北京千鋒互聯科技有限公司

本規範旨在為日常Go專案開發提供一個程式碼的規範指導,方便團隊形成一個統一的程式碼風格,提高程式碼的可讀性,規範性和統一性。本規範將從命名規範,註釋規範,程式碼風格和 Go 語言提供的常用的工具這幾個方面做一個說明。該規範參考了 go 語言官方程式碼的風格制定。

一、 命名規範

命名是程式碼規範中很重要的一部分,統一的命名規則有利於提高的程式碼的可讀性,好的命名僅僅通過命名就可以獲取到足夠多的資訊。

Go在命名時以字母a到Z或a到Z或下劃線開頭,後面跟著零或更多的字母、下劃線和數字(0到9)。Go不允許在命名時中使用@、$和%等標點符號。Go是一種區分大小寫的程式語言。因此,Manpower和manpower是兩個不同的命名。

  1. 當命名(包括常量、變數、型別、函式名、結構欄位等等)以一個大寫字母開頭,如:Group1,那麼使用這種形式的識別符號的物件就可以被外部包的程式碼所使用(客戶端程式需要先匯入這個包),這被稱為匯出(像面嚮物件語言中的 public);
  2. 命名如果以小寫字母開頭,則對包外是不可見的,但是他們在整個包的內部是可見並且可用的(像面嚮物件語言中的 private )

1、包命名:package

保持package的名字和目錄保持一致,儘量採取有意義的包名,簡短,有意義,儘量和標準庫不要衝突。包名應該為小寫單詞,不要使用下劃線或者混合大小寫。

package demo

package main

2、 檔案命名

儘量採取有意義的檔名,簡短,有意義,應該為小寫單詞,使用下劃線分隔各個單詞。

my_test.go

3、 結構體命名

  • 採用駝峰命名法,首字母根據訪問控制大寫或者小寫

  • struct 申明和初始化格式採用多行,例如下面:

// 多行申明
type User struct{
    Username  string
    Email     string
}

// 多行初始化
u := User{
    Username: "astaxie",
    Email:    "[email protected]",
}

4、 介面命名

  • 命名規則基本和上面的結構體型別
  • 單個函式的結構名以 “er” 作為字尾,例如 Reader , Writer 。
type Reader interface {
        Read(p []byte) (n int, err error)
}

5、變數命名

  • 和結構體類似,變數名稱一般遵循駝峰法,首字母根據訪問控制原則大寫或者小寫,但遇到特有名詞時,需要遵循以下規則:
    • 如果變數為私有,且特有名詞為首個單詞,則使用小寫,如 apiClient
    • 其它情況都應當使用該名詞原有的寫法,如 APIClient、repoID、UserID
    • 錯誤示例:UrlArray,應該寫成 urlArray 或者 URLArray
  • 若變數型別為 bool 型別,則名稱應以 Has, Is, Can 或 Allow 開頭
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool

6、常量命名

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

const APP_VER = "1.0"

如果是列舉型別的常量,需要先建立相應型別:

type Scheme string

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

7、 關鍵字

下面的列表顯示了Go中的保留字。這些保留字不能用作常量或變數或任何其他識別符號名稱。

二、註釋

Go提供C風格的/* */塊註釋和C ++風格的//行註釋。行註釋是常態;塊註釋主要顯示為包註釋,但在表示式中很有用或禁用大量程式碼。

  • 單行註釋是最常見的註釋形式,你可以在任何地方使用以 // 開頭的單行註釋
  • 多行註釋也叫塊註釋,均已以 /* 開頭,並以 */ 結尾,且不可以巢狀使用,多行註釋一般用於包的文件描述或註釋成塊的程式碼片段

go 語言自帶的 godoc 工具可以根據註釋生成文件,生成可以自動生成對應的網站( golang.org 就是使用 godoc 工具直接生成的),註釋的質量決定了生成的文件的質量。每個包都應該有一個包註釋,在package子句之前有一個塊註釋。對於多檔案包,包註釋只需要存在於一個檔案中,任何一個都可以。包評論應該介紹包,並提供與整個包相關的資訊。它將首先出現在godoc頁面上,並應設定下面的詳細文件。

詳細的如何寫註釋可以
參考:http://golang.org/doc/effective_go.html#commentary

1、包註釋

每個包都應該有一個包註釋,一個位於package子句之前的塊註釋或行註釋。包如果有多個go檔案,只需要出現在一個go檔案中(一般是和包同名的檔案)即可。 包註釋應該包含下面基本資訊(請嚴格按照這個順序,簡介,建立人,建立時間):

  • 包的基本簡介(包名,簡介)
  • 建立者,格式: 建立人: rtx 名
  • 建立時間,格式:建立時間: yyyyMMdd

例如 util 包的註釋示例如下

// util 包, 該包包含了專案共用的一些常量,封裝了專案中一些共用函式。
// 建立人: hanru
// 建立時間: 20190419

2、結構(介面)註釋

每個自定義的結構體或者介面都應該有註釋說明,該註釋對結構進行簡要介紹,放在結構體定義的前一行,格式為: 結構體名, 結構體說明。同時結構體內的每個成員變數都要有說明,該說明放在成員變數的後面(注意對齊),例項如下:

// User , 使用者物件,定義了使用者的基礎資訊
type User struct{
    Username  string // 使用者名稱
    Email     string // 郵箱
}

3、函式(方法)註釋

每個函式,或者方法(結構體或者介面下的函式稱為方法)都應該有註釋說明,函式的註釋應該包括三個方面(嚴格按照此順序撰寫):

  • 簡要說明,格式說明:以函式名開頭,“,”分隔說明部分
  • 引數列表:每行一個引數,引數名開頭,“,”分隔說明部分
  • 返回值: 每行一個返回值

示例如下:

// NewtAttrModel , 屬性資料層操作類的工廠方法
// 引數:
//      ctx : 上下文資訊
// 返回值:
//      屬性操作類指標
func NewAttrModel(ctx *common.Context) *AttrModel {
}

4、程式碼邏輯註釋

對於一些關鍵位置的程式碼邏輯,或者區域性較為複雜的邏輯,需要有相應的邏輯說明,方便其他開發者閱讀該段程式碼,例項如下:

// 從 Redis 中批量讀取屬性,對於沒有讀取到的 id , 記錄到一個數組裡面,準備從 DB 中讀取
xxxxx
xxxxxxx
xxxxxxx

5、註釋風格

統一使用中文註釋,對於中英文字元之間嚴格使用空格分隔, 這個不僅僅是中文和英文之間,英文和中文標點之間也都要使用空格分隔,例如:

// 從 Redis 中批量讀取屬性,對於沒有讀取到的 id , 記錄到一個數組裡面,準備從 DB 中讀取

上面 Redis 、 id 、 DB 和其他中文字元之間都是用了空格分隔。

  • 建議全部使用單行註釋
  • 和程式碼的規範一樣,單行註釋不要過長,禁止超過 120 字元。

三、程式碼風格

1、縮排和折行

  • 縮排直接使用 gofmt 工具格式化即可(gofmt 是使用 tab 縮排的);
  • 折行方面,一行最長不超過120個字元,超過的請使用換行展示,儘量保持格式優雅。

我們使用Goland開發工具,可以直接使用快捷鍵:ctrl+alt+L,即可。

2、語句的結尾

Go語言中是不需要類似於Java需要冒號結尾,預設一行就是一條資料

如果你打算將多個語句寫在同一行,它們則必須使用 ;

3、括號和空格

括號和空格方面,也可以直接使用 gofmt 工具格式化(go 會強制左大括號不換行,換行會報語法錯誤),所有的運算子和運算元之間要留空格。

// 正確的方式
if a > 0 {

} 

// 錯誤的方式
if a>0  // a ,0 和 > 之間應該空格
{       // 左大括號不可以換行,會報語法錯誤

}

4、import 規範

import在多行的情況下,goimports會自動幫你格式化,但是我們這裡還是規範一下import的一些規範,如果你在一個檔案裡面引入了一個package,還是建議採用如下格式:

import (
    "fmt"
)

如果你的包引入了三種類型的包,標準庫包,程式內部包,第三方包,建議採用如下方式進行組織你的包:

import (
    "encoding/json"
    "strings"

    "myproject/models"
    "myproject/controller"
    "myproject/utils"

    "github.com/astaxie/beego"
    "github.com/go-sql-driver/mysql"
)   

有順序的引入包,不同的型別採用空格分離,第一種實標準庫,第二是專案包,第三是第三方包。

在專案中不要使用相對路徑引入包:

// 這是不好的匯入
import “../net”

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

但是如果是引入本專案中的其他包,最好使用相對路徑。

5、錯誤處理

  • 錯誤處理的原則就是不能丟棄任何有返回err的呼叫,不要使用 _ 丟棄,必須全部處理。接收到錯誤,要麼返回err,或者使用log記錄下來
  • 儘早return:一旦有錯誤發生,馬上返回
  • 儘量不要使用panic,除非你知道你在做什麼
  • 錯誤描述如果是英文必須為小寫,不需要標點結尾
  • 採用獨立的錯誤流進行處理
// 錯誤寫法
if err != nil {
    // error handling
} else {
    // normal code
}

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

6、測試

單元測試檔名命名規範為 example_test.go
測試用例的函式名稱必須以 Test 開頭,例如:TestExample
每個重要的函式都要首先編寫測試用例,測試用例和正規程式碼一起提交方便進行迴歸測試

四、常用工具

上面提到了很過規範, go 語言本身在程式碼規範性這方面也做了很多努力,很多限制都是強制語法要求,例如左大括號不換行,引用的包或者定義的變數不使用會報錯,此外 go 還是提供了很多好用的工具幫助我們進行程式碼的規範,

gofmt
大部分的格式問題可以通過gofmt解決, gofmt 自動格式化程式碼,保證所有的 go 程式碼與官方推薦的格式保持一致,於是所有格式有關問題,都以 gofmt 的結果為準。

goimport
我們強烈建議使用 goimport ,該工具在 gofmt 的基礎上增加了自動刪除和引入包.

go get golang.org/x/tools/cmd/goimports

go vet
vet工具可以幫我們靜態分析我們的原始碼存在的各種問題,例如多餘的程式碼,提前return的邏輯,struct的tag是否符合標準等。

go get golang.org/x/tools/cmd/vet

使用如下:

go vet .