effective go 筆記

格式化

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 : 打印類型

參考

effiective go

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章