Golong學習之常見開發陷阱,你遇到過幾個?
阿新 • • 發佈:2019-01-07
Go作為一種簡便靈巧的語言,深受開發者的喜愛。但對於初學者來說,要想輕鬆駕馭它,還得做好細節學習工作。
初學者應該注意的地方:
- 大括號不能獨立成行。
- 未使用變數錯誤——對於全域性變數和函式引數變數,是可以定義後不使用的。但是對於函式內部變數來說,如果進行定義後不進行使用,編譯器會提示錯誤。
- 匯入包未呼叫錯誤——匯入包後,如果不進行呼叫,例如函式,介面,結構及變數等物件,那麼會出現編譯錯誤。這裡建議使用空白表示符“_”來避免類似錯誤。
- 變數簡寫只適用於函式內部。
- 重新定義變數要使用簡寫宣告——你不能在一個獨立的語句中重新定義一個變數,但在複合變數場合是允許的。重新定義的變數需存在於同一區塊,否則會產生一個陰影變數。
- 意外的變數——變數簡寫語法由於十分簡便,因此很容易會把它作為一個常規的指派操作。雖然可以通過編譯,但是其結果卻不是我們想要的。
- 不能使用“nil”來定義一個沒有型別的變數——“nil”關鍵字可用於表示“0值”,例如在介面,函式,指標等物件中。但如果把它用於定義一個沒有進行型別宣告的變數,將會導致編譯錯誤,因為編譯器無法確定變數型別。
- 使用“nil”切片(Slices)和圖(Maps)——為“nil”切片新增物件是可以的,但對於圖來說,這樣會造成執行緩慢。
- 圖容量——可以在建立時設定圖的容量,但是不用對圖使用cap()。
- 字串不能為“nil”。
- 陣列函式引數——對於C/C++開發者來說,陣列如同指標;當把陣列傳入函式時,函式會引用相同的記憶體位置,所以能夠更新原始資料。但在Go中,陣列是值,因此當把陣列傳入函式時,得到的是原始陣列資料的副本。因此如果想更新陣列資料,這個造成問題。
- 切片和陣列“範圍(range)”裡的異常——在使用for-in或foreach語句時會遇到該問題。在Go中,range的定義是有所不同的。它會產生兩個值:第一個為索引項,第二個說項的資料。
- 單維度的切片和數——要建立一個動態多維度陣列,要使用獨立切片。首先,要建立外層切片;然後,要對每個內聯切片進行分配。每個內聯切片對於其它切片來說是獨立的。
- 訪問不存在的圖鍵——如果想知道一個給定圖記錄是否存在,應該通過檢查來自圖訪問操作的第二個值。
- 不可改變的字串——如果想通過索引運算子來更新一個字串變數中的獨立字元是會出現錯誤的,由於字串是隻讀的位元組片。正確做法是使用一個單位元組片進行操作而不是轉成字串型別進行操作。
- 字串和位元組片轉換——當把字串轉換為位元組片時,你得到是一份完整的原始資料。Go提供了一對
[]byte to string,string to []byte
的優化轉換操作,以防止造成額外分配。 - 字串和索引運算子——字串中的索引運算子返回的是位元組值而不是字元。
- 字串不總是UTF8文字——字串沒有被限定為UTF8文字。它們可以包含任何位元組。只有當使用字串常數時才是UTF8文字。
- 字串長度——Go中應使用RuneCountInString()函式來取得字串長度值而不是len()函式。
- 多行切片,陣列,和圖定義中缺少逗號。
- log.Fatal和log.Panic:日誌庫提供了不同的日誌級別。
- 預置資料結構運算是不同步的。
- 在range中的字串迭代值。
- 使用for range來進行圖迭代。
- Switch語句的注意事項:switch語句的case區塊預設是隔斷的。
- 遞增和遞減:Go中是不支援i++或++i的遞增/減操作的。
- 按位不是運算子:很多語言使用~來作為一元邏輯非運算子,而Go中則使用^。
- 運算子優先順序差異。
- 匯出結構域是沒有編碼。
- 程式結束時沒有銷燬Go執行緒。
- 當目標接收器就緒時就傳送一個緩衝區通道返回。
- 封閉通道傳送的問題。
- 使用“nil”通道。
- 有值接收器的方法不能用於改變原始值。
中級開發者應該注意的地方:
- 關閉HTTP響應。
- 關閉HTTP連線。
- 結構,陣列,切片和圖的比較。
- 可以使用==運算子來比較不同的結構變數。
- 從異常中恢復。
- 可以使用recover()來捕獲/攔截異常。
- 更新和引用切片,陣列,及圖“range”的項值。
- 切片的“隱藏”資料。
- 切片資料的錯誤。
- “變味”的切片。
- 型別宣告和方法。
- for switch和for select程式碼塊的終止。
- for語句中的迭代變數和結束。
- 延遲的函式呼叫引數求值。
- 延遲函式呼叫執行。
- 錯誤型別的判斷。
- 斷開的Go執行緒和資源洩漏。
高階開發者應該注意的地方:
- 對值例項使用指標接收方法。
- 更新圖值域。
- “nil”介面和“nil”介面值。
- 堆疊變數。
- GOMAXPROCS,併發,並行化。
- 搶先排程。
以“大括號不能獨立成行”為例:
錯誤寫法:
package main
import "fmt"
func main()
{ //error, can't have the opening brace on a separate line
fmt.Println("hello there!")
}
編譯錯誤提示:
/tmp/sandbox826898458/main.go:6: syntax error: unexpected semicolon or newline before {
正確寫法:
package main
import "fmt"
func main() {
fmt.Println("works!")
}
如果你經常瀏覽Go語言官方論壇的文章,或許對上述種種“灰色地帶”不陌生。但是如果是剛接觸Go語言,我建議還是要多看官方的教程和多實踐。這樣對於儘早學會Go語言是很有幫助的。
本文所列舉的這些”陷阱“是開發者在開發過程中較為常見的,關於如何避免以及如何正確輸寫,請檢視原文devs.cloudimmunity,由於篇幅較長,筆者並沒有逐一翻譯,還請諒解。感興趣的朋友不妨在評論下方發表下自己的看法以及給出解決方法。