我們必須遵循的 12 個 Go 語言最佳實踐
本文旨在提供一個切實的指導,在 Go 語言中實現最佳實踐和設計模式。這些程式設計技巧可以幫助開發者編寫出較好的程式碼。你一定已經讀過了Go Tutorial 和Effective Go 。
為了讓大家對這些程式設計技巧有更加深刻的認識,我在討論這些最佳實踐的時候會附加一些示例程式碼。
那些編寫了許多優秀程式碼的大師們,一直在使用一些 Go 語言程式設計實踐或者說是程式設計技巧。
下面列出了其中一些最好的程式設計實踐,可以使寫出的程式碼簡單、易懂並且易於維護
1、使用 gofmt
2、通過首先處理錯誤來避免程式碼巢狀
3、錯誤字串
4、錯誤處理
5、儘量避免程式碼重複
6、變數名宣告
7、用型別選擇語句來處理特例
8、在型別選擇語句中宣告變數
9、重要的程式碼要放在原始檔的前面
10、點匯入
11、註釋程式碼
12、註釋語句規範
1、使用gofmt
對原始碼執行 gofmt 命令,會自動修正大部分粗心導致的問題。幾乎全世界的 Go 語言開發者都在用 gofmt。
gofmt 首先讀取原始碼,然後輸出經過縮排、垂直對齊甚至規範註釋後的程式碼。
命令和選項
gofmt 檔名 - 輸出格式化後的程式碼
gofmt -w 檔名 - 重新格式化程式碼並更新檔案
gofmt -r'rule' 檔名 - 格式化程式碼前執行指定的規則
gofmt 包所在的路徑 - 格式化整個包下的原始檔
下面是使用 gofmt 的一些小例子
檔名:demo.go
package main import "fmt" // this is demo to format code // with gofmt command var a int=10; var b int=15; var c string= "Welcome to Agira"; func print(){ fmt.Println("Value for a,b and c is : "); fmt.Println(a); fmt.Println((b)); fmt.Println(c); }
輸入命令:$ gofmt demo.go
輸出結果:
package main import "fmt" // this is demo to format code // with gofmt command var a int = 10 var b int = 15 var c string =“Welcome to Agira” func print() { fmt.Println("Value for a,b and c is : ") fmt.Println(a) fmt.Println((b)) fmt.Println(c) }
2、通過首先處理錯誤來避免程式碼巢狀
避免使用多重條件或者巢狀條件,當我們處理後面的程式碼前需要處理錯誤,例如下面的程式碼
err := request() if err != nil { // handling error } else { // normal code }
我們可以用下面的方式代替
err := request() if err != nil { // handling error return // or continue, etc. } // proceed to further
巢狀條件語句越少,讀者越容易理解
如果 if 語句中包含初始化語句,例如:
if x, err := f(); err != nil { // handling error return } else { // use x }
我們應該在程式碼中定義一個短變數,在之後的 if 語句中使用這個變數
x, err := f() if err != nil { // handling error return } // use x
3、錯誤字串
錯誤字串首字母不應該大寫(除非是以一些特殊的名詞或者縮寫開頭)。
例如:
fmt.Errorf("Something went wrong") 應該寫成 fmt.Errorf("something went wrong")
4、錯誤處理
不要用 _ 來忽略錯誤。如果一個函式可能返回錯誤資訊,檢查函式的返回值 ,確認函式是否執行成功了。更好的做法是處理這個錯誤並返回,不然的話如果出現任何異常程式會產生一個 panic 錯誤
不要用 panic 錯誤
不要在正常處理流程中使用 panic, 那種情況下可以用 error 和多重返回值。
5、儘可能避免重複
如果你想在控制模組和資料模組使用同一個型別結構,建立一個公共檔案,在那裡宣告這個型別
6、變數名宣告
在 Go 程式設計中最好用短的變數名,尤其是那些作用域比較有限的區域性變數
用c
而不是lineCount
用i
而不是sliceIndex
1、基本規則:距離宣告的地方越遠,變數名需要越具可讀性。
2、作為一個函式接收者,1、2 個字母的變數比較高效。
3、像迴圈指示變數和輸入流變數,用一個單字母就可以。
4、越不常用的變數和公共變數,需要用更具說明性的名字。
7、用型別選擇語句來處理特例
如果你不確定 iterface{} 是什麼型別,就可以用型別選擇語句
例如:
func Write(v interface{}) { switch v.(type) { case string: s := v.(string) fmt.Printf(“%T\n”,s) case int: i := v.(int) fmt.Printf(“%T\n”,i) } }
8、在型別選擇語句中宣告變數
在型別選擇語句中宣告的變數,在每個分支中會自動轉化成正確的型別
例如:
func Write(v interface{}) { switch x := v.(type) { case string: fmt.Printf(“%T\n”,x) case int: fmt.Printf(“%T\n”,x) } }
9、重要的程式碼要放在原始檔的前面
如果你有像版權宣告、構建標籤、包註釋這樣的重要資訊,儘量寫在原始檔的靠前位置。 我們可以用空行把匯入語句分成若干個組,標準庫放在最前面。
import ( "fmt" "io" "log" "golang.org/x/net/websocket" )
在接下來的程式碼中,首先寫重要的型別,在最後寫一些輔助型的函式和型別。
10、點匯入
點匯入可以測試迴圈依賴。並且它不會成為被測試程式碼的一部分:
package foo_test import ( "bar/testutil" // also imports "foo" . "foo" )
這樣的情況下,測試程式碼不能放在 foo 包中,因為它引入了 bar/testutil包,而它匯入了 foo。所以我們用點匯入 的形式讓檔案假裝是包的一部分,而實際上它並不是。除了這個使用情形外,最好不要用點匯入。因為它會讓讀者閱讀程式碼時更加困難,因為很難確定像 Quux 這樣的名字是當前包的頂層宣告還是引入的包。
11、註釋程式碼
在包名字之前新增包相關的註釋
// Package playground registers an HTTP handler at “/compile” that // proxies requests to the golang.org playground service. package playground
出現在 godoc 中的識別符號,需要適當的註釋
// Author represents the person who wrote and/or is presenting the document. type Author struct { Elem []Elem } // TextElem returns the first text elements of the author details. // This is used to display the author’ name, job title, and company // without the contact details. func (p *Author) TextElem() (elems []Elem) {
12、註釋語句規範
即使註釋語句看上去有一些冗餘,也需要是一個完整的句子,。這樣會讓它們在 godoc 中有更的格式化效果。註釋需要以被註釋的名字開頭,以點號結尾。
// Request represents a request to run a command. type Request struct { … // Encode writes the JSON encoding of req to w. func Encode(w io.Writer, req *Request) { … and so on.
希望這些 Go 語言最佳實踐可以幫助你提高程式碼質量。我們也列出了其它許多技術的最佳實踐,可以在largest blog repository 找到。有其它問題可以通過[email protected] 聯絡我們