Go編碼規範指南
Go編碼規範指南
序言
看過很多方面的編碼規範,可能每一家公司都有不同的規範,這份編碼規範是寫給我自己的,同時希望我們公司內部同事也能遵循這個規範來寫Go程式碼。
如果你的程式碼沒有辦法找到下面的規範,那麼就遵循標準庫的規範,多閱讀標準庫的原始碼,標準庫的程式碼可以說是我們寫程式碼參考的標杆。
格式化規範
go預設已經有了gofmt工具,但是我們強烈建議使用goimport工具,這個在gofmt的基礎上增加了自動刪除和引入包.
go get golang.org/x/tools/cmd/goimports
不同的編輯器有不同的配置, sublime的配置教程:http://michaelwhatcott.com/gosublime-goimports/
LiteIDE預設已經支援了goimports,如果你的不支援請點選屬性配置->golangfmt->勾選goimports
儲存之前自動fmt你的程式碼。
行長約定
一行最長不超過80個字元,超過的請使用換行展示,儘量保持格式優雅。
go vet
vet工具可以幫我們靜態分析我們的原始碼存在的各種問題,例如多餘的程式碼,提前return的邏輯,struct的tag是否符合標準等。
go get golang.org/x/tools/cmd/vet
使用如下:
go vet .
package名字
保持package的名字和目錄保持一致,儘量採取有意義的包名,簡短,有意義,儘量和標準庫不要衝突。
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”
變數申明
變數名採用駝峰標準,不要使用_
來命名變數名,多個變數申明放在一起
var (
Found bool
count int
)
在函式外部申明必須使用var,不要採用:=
,容易踩到變數的作用域的問題。
自定義型別的string迴圈問題
如果自定義的型別定義了String方法,那麼在列印的時候會產生隱藏的一些bug
type MyInt int
func (m MyInt) String() string {
return fmt.Sprint(m) //BUG:死迴圈
}
func(m MyInt) String() string {
return fmt.Sprint(int(m)) //這是安全的,因為我們內部進行了型別轉換
}
避免返回命名的引數
如果你的函式很短小,少於10行程式碼,那麼可以使用,不然請直接使用型別,因為如果使用命名變數很 容易引起隱藏的bug
func Foo(a int, b int) (string, ok){
}
當然如果是有多個相同型別的引數返回,那麼命名引數可能更清晰:
func (f *Foo) Location() (float64, float64, error)
下面的程式碼就更清晰了:
// Location returns f's latitude and longitude.
// Negative values mean south and west, respectively.
func (f *Foo) Location() (lat, long float64, err error)
錯誤處理
錯誤處理的原則就是不能丟棄任何有返回err的呼叫,不要採用_
丟棄,必須全部處理。接收到錯誤,要麼返回err,要麼實在不行就panic,或者使用log記錄下來
error 資訊
error的資訊不要採用大寫字母,儘量保持你的錯誤簡短,但是要足夠表達你的錯誤的意思。
長句子列印或者呼叫,使用引數進行格式化分行
我們在呼叫fmt.Sprint
或者log.Sprint
之類的函式時,有時候會遇到很長的句子,我們需要在引數呼叫處進行多行分割:
下面是錯誤的方式:
log.Printf(“A long format string: %s %d %d %s”, myStringParameter, len(a),
expected.Size, defrobnicate(“Anotherlongstringparameter”,
expected.Growth.Nanoseconds() /1e6))
應該是如下的方式:
log.Printf(
“A long format string: %s %d %d %s”,
myStringParameter,
len(a),
expected.Size,
defrobnicate(
“Anotherlongstringparameter”,
expected.Growth.Nanoseconds()/1e6,
),
)
注意閉包的呼叫
在迴圈中呼叫函式或者goroutine方法,一定要採用顯示的變數呼叫,不要再閉包函式裡面呼叫迴圈的引數
fori:=0;i<limit;i++{
go func(){ DoSomething(i) }() //錯誤的做法
go func(i int){ DoSomething(i) }(i)//正確的做法
}
http://golang.org/doc/articles/race_detector.html#Race_on_loop_counter
在邏輯處理中禁用panic
在main包中只有當實在不可執行的情況採用panic,例如檔案無法開啟,資料庫無法連線導致程式無法 正常執行,但是對於其他的package對外的介面不能有panic,只能在包內採用。
強烈建議在main包中使用log.Fatal來記錄錯誤,這樣就可以由log來結束程式。
註釋規範
註釋可以幫我們很好的完成文件的工作,寫得好的註釋可以方便我們以後的維護。詳細的如何寫註釋可以 參考:http://golang.org/doc/effective_go.html#commentary
bug註釋
針對程式碼中出現的bug,可以採用如下教程使用特殊的註釋,在godocs可以做到註釋高亮:
// BUG(astaxie):This divides by zero.
var i float = 1/0
http://blog.golang.org/2011/03/godocdocumentinggocode.html
struct規範
struct申明和初始化格式採用多行:
定義如下:
type User struct{
Username string
Email string
}
初始化如下:
u := User{
Username: "astaxie",
Email: "astaxie@gmail.com",
}
recieved是值型別還是指標型別
到底是採用值型別還是指標型別主要參考如下原則:
func(w Win) Tally(playerPlayer)int //w不會有任何改變
func(w *Win) Tally(playerPlayer)int //w會改變資料
更多的請參考:https://code.google.com/p/go-wiki/wiki/CodeReviewComments#Receiver_Type
帶mutex的struct必須是指標receivers
如果你定義的struct中帶有mutex,那麼你的receivers必須是指標
參考資料
相關文章
- Go 編碼規範指南Go
- Android編碼規範指南Android
- Uber Go 語言編碼規範Go
- PHP 編碼風格規範指南PHP
- 最全面的 Android 編碼規範指南Android
- Go 語言程式碼風格規範-指南篇Go
- 編碼規範系列:css規範CSS
- JavaScript 風格指南/編碼規範(Airbnb公司版)JavaScriptAI
- 程式碼規範之前端編寫碼規範前端
- CSS編碼規範CSS
- Javascript編碼規範JavaScript
- html編碼規範HTML
- Swift 編碼規範Swift
- PHP編碼規範PHP
- SQL 編碼規範SQL
- WEB前端編碼規範Web前端
- python編碼規範Python
- 前端安全編碼規範前端
- 前端html編碼規範前端HTML
- android 編碼規範Android
- HTML,CSS編碼規範HTMLCSS
- 阿里Java編碼規範阿里Java
- [轉]PHP編碼規範PHP
- C# 編碼規範C#
- Java 編碼規範 (轉)Java
- java編碼規範 (轉)Java
- 送給學Go或者轉Go同學的一套編碼規範Go
- 網易郵箱前端Javascript編碼規範:類規範前端JavaScript
- Java語言編碼規範Java
- PHP編碼風格規範PHP
- HTML編碼規範建議HTML
- 前端開發編碼規範前端
- iOS的編碼規範(1.1)iOS
- HTML/CSS/JS編碼規範HTMLCSSJS
- React/JSX 編碼規範ReactJS
- Google的Java編碼規範GoJava
- iOS團隊編碼規範iOS
- java編碼規範(2) (轉)Java