格式化
golang 提供了gofmt程序(也可以使用go fmt,它以包爲處理對象而非源文件)將go程序按照標準風格縮緊、對齊,保留註釋兵在需要時重新格式化;
比如,下面程序你無需花時間將結構體中的字段註釋對齊,gofmt 會處理的;
type T struct {
name string // name of the object
value int // its value
}
格式化後:
type T struct {
name string // name of the object
value int // its value
}
格式化的細節
- 縮進
我們使用製表符縮進,gofmt 默認也使用它。在你認爲確實有必要時再使用空格
- 行的長度
Go 對行的長度沒有限制,最好不要大於80個字符
- 括號
控制結構(if for 和switch) 在語法上並不需要圓括號。
註釋
- 支持 C 語言風格註釋 /* */
- C++ 風格的行註釋 //。
行註釋更爲常用,/**/ 主要用於包的註釋,當然也可以在禁用一大段代碼時使用。
godoc 既是一個程序,又是一個 Web 服務器,它對 Go 的源碼進行處理,並提取包中的文檔內容。 出現在頂級聲明之前,且與該聲明之間沒有空行的註釋,將與該聲明一起被提取出來,作爲該條目的說明文檔。 這些註釋的類型和風格決定了 godoc 生成的文檔質量。
每個包都應該包含一段包註釋,即放在package 之前。對於包含多個文件的包, 包註釋只需出現在其中的任一一個文件中即可。包註釋應該在整體上對該包進行介紹,並提供包的相關信息。
在程序中,每個可導出的名稱都應該有文檔註釋。文檔註釋最好是完整的句子,這樣它才能適應各種自動化的展示。第一句應當以被聲明的東西開頭,並且是單句的摘要。
// Compile parses a regular expression and returns, if successful, a Regexp
// object that can be used to match against text.
func Compile(str string) (regexp *Regexp, err error) {
命名
獲取器
不要將Get放到獲取器的名字中,既不符合習慣,也沒有必要。比如有個名爲ower(小寫,未導出)的字段,其獲取器應當名爲Ower(大寫,可導出)而非GetOwner。若要提供設置器方法,SetOwner 是個不錯的選擇。
owner := obj.Owner()
if owner != user {
obj.SetOwner(user)
}
接口名字
- 只有一個方法的接口應該以該方法的名字加上 -er後綴來命名, 如Reader、Writer、Formatter、CloseNotifier等。
- Read、Write、Close、Flush、 String 等都具有典型的簽名和意義,除非明確他們的簽名和意義,否則不要使用。
駝峯記法
Go 中約定使用駝峯記法 MixedCaps 或 mixedCaps 而非下劃線的方式來對單詞名稱進行命名。
分號
Go 語言也是分號結尾的,只是詞法分析器按照簡單的規則自動插入分號,我們寫代碼的適合就不需要手動添加了;這條規則是“如果新行前的最後一個標記爲標識符(包括int 和 float64 這類的單詞)、數值或者字符串常量之類的基本子面或以下標記之一
break continue fallthrough return ++ – ) }
則詞法分析就在最後插入分號。”
- 分號在大括號之前直接省略。
- 不能將控制結構的左大括號放在下一行
for
與C類比
// c for
for init; condition; post {}
// c while
for condition {}
// c for( ;; )
for {}
switch
switch 多個條件相同處理方式,可以用逗號列舉
func shouldEscape(c byte) bool {
switch c {
case ' ', '?', '&', '=', '#', '+', '%':
return true
}
return f
}
break 搭配標籤可以退出循環;
continue 也可以搭配標籤,不過必須要要在循環中;
函數
可命名返回結果
- Go的函數的返回結果可被命名,在函數執行的適合會將命名參數初始化其相應的零值。
- 如果沒有明確返回,命名參數的當前值就是返回結果。
Defer
- 執行順序LIFO。
- 求值是在推遲執行時進行,而非在調用推遲函數時。
Data
new 與 make
new : 用來分配內存的內建函數,但是不會初始化內存,只是將內存設置爲零值。
make : 只用於創建slice map 和channel ,並返回一個類型爲T(而非 *T)的已經初始化(而非零值)的值。
數組
在Go中:
- 數組是值。將一個數組賦予另一個數組會複製其所有元素。
- 將某個數組傳入某個函數,它將收到該數組的一個副本而非指針。
- 數組的大小是其類型的一部分。類型[10]int 和 [20]int是不同的類型。
切片
- 切片是對數組的引用。
- 切片的容量可通過內建函數cap獲得,它將給出該切片可獲取的最大長度。
- 超出容量,會重新分配切片。
- append 可修改slice 的元素,但是切片自身(其運行時數據結構包含指針、長度和容量)是通過值傳遞的。
map
- 健可以是任何可以支持相等性操作的類型,切片不可以;
- 試圖獲取不存在的值,返回該類型的零值;
打印
- %d : 十進制
- %x : 十六進制
- %v : 通用格式,打印值
&{7 -2.35 abc def} - %+v : 給值添加上字段名
&{a:7 b:-2.35 c:abc def} - %#v : 完全按照Go語法打印。
&main.T{a:7, b:-2.35, c:“abc\tdef”} - %T : 打印類型