這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
一行最長不超過80個字元,超過的使用換行展示,盡量保持格式優雅。
* 注釋
在編碼階段應該同步寫好變數、函數、包的注釋,最後可以利用godoc匯出文檔。注釋必須是完整的句子,句子的結尾應該用句號作為結尾(英文句號)。注釋推薦用英文,可以在寫代碼過程中鍛煉英文的閱讀和書寫能力。而且用英文不會出現各種編碼的問題。
每個包都應該有一個包注釋,一個位於package子句之前的塊注釋或行注釋。包如果有多個go檔案,只需要出現在一個go檔案中即可。
// ping包實現了常用的ping相關的函數package ping
匯出函數注釋,第一條語句應該為一條概括語句,並且使用被聲明的名字作為開頭。
// 求a和b的和,返回sum。func Myfunction(sum int) (a, b int) {
命名
- 需要注釋來補充的命名就不算是好命名。
- 使用可搜尋的名稱:單字母名稱和數字常量很難從一大堆文字中搜尋出來。單字母名稱僅適用於短方法中的本地變數,名稱長短應與其範圍相對應。若變數或常量可能在代碼中多處使用,則應賦其以便於搜尋的名稱。
- 做有意義的區分:Product和ProductInfo和ProductData沒有區別,NameString和Name沒有區別,要區分名稱,就要以讀者能鑒別不同之處的方式來區分 。
- 函數命名規則:駝峰式命名,名字可以長但是得把功能,必要的參數描述清楚,函數名名應當是動詞或動詞短語,如postPayment、deletePage、save。並依Javabean標準加上get、set、is首碼。例如:xxx + With + 需要的參數名 + And + 需要的參數名 + …..
- 結構體命名規則:結構體名應該是名詞或名詞短語,如Custome、WikiPage、Account、AddressParser,避免使用Manager、Processor、Data、Info、這樣的類名,類名不應當是動詞。
- 包名命名規則:包名應該為小寫單詞,不要使用底線或者混合大小寫。
- 介面命名規則:單個函數的介面名以”er”作為尾碼,如Reader,Writer。介面的實現則去掉“er”。
type Reader interface { Read(p []byte) (n int, err error)}
兩個函數的介面名綜合兩個函數名
type WriteFlusher interface { Write([]byte) (int, error) Flush() error}
三個以上函數的介面名,抽象這個介面的功能,類似於結構體名
type Car interface { Start([]byte) Stop() error Recover()}
常量均需使用全部大寫字母組成,並使用底線分詞:
const APP_VER = "1.0"
如果是枚舉類型的常量,需要先建立相應類型:
type Scheme stringconst ( HTTP Scheme = "http" HTTPS Scheme = "https")
如果模組的功能較為複雜、常量名稱容易混淆的情況下,為了更好地區分枚舉類型,可以使用完整的首碼:
type PullRequestStatus intconst ( PULL_REQUEST_STATUS_CONFLICT PullRequestStatus = iota PULL_REQUEST_STATUS_CHECKING PULL_REQUEST_STATUS_MERGEABLE)
var isExist boolvar hasConflict boolvar canManage boolvar allowGitHook bool
// A GonicMapper that contains a list of common initialisms taken from golang/lintvar 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申明和初始化格式採用多行:
定義如下:
type User struct{ Username string Email string}
初始化如下:
u := User{ Username: "test", Email: "test@gmail.com",}
if err := file.Chmod(0664); err != nil { return err}
for
採用短聲明建立局部變數
sum := 0for i := 0; i < 10; i++ { sum += i}
return
儘早return:一旦有錯誤發生,馬上返回
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作為函數的值返回,必須對error進行處理
- 錯誤描述如果是英文必須為小寫,不需要標點結尾
- 採用獨立的錯誤流進行處理
不要採用下面的處理錯誤寫法
if err != nil { // error handling } else { // normal code }
採用下面的寫法
if err != nil { // error handling return // or continue, etc. } // normal code
使用函數的傳回值時,則採用下面的方式
x, err := f()if err != nil { // error handling return}// use x
盡量不要使用panic,除非你知道你在做什麼
對import的包進行分組管理,用分行符號分割,而且標準庫作為分組的第一組。如果你的包引入了三種類型的包,標準庫包,程式內部包,第三方包,建議採用如下方式進行組織你的包
package mainimport ( "fmt" "os" "kmg/a" "kmg/b" "code.google.com/a" "github.com/b")
在項目中不要使用相對路徑引入包:
// 錯誤樣本import “../net”// 正確的做法import “github.com/repo/proj/src/net”
goimports會自動幫你格式化
參數傳遞
- 對於少量資料,不要傳遞指標
- 對於大量資料的struct可以考慮使用指標
- 傳入參數是map,slice,chan不要傳遞指標,因為map,slice,chan是參考型別,不需要傳遞指標的指標
單元測試
單元測試檔案名稱命名規範為 example_test.go
測試案例的函數名稱必須以 Test 開頭,例如:TestExample