Go 語言最佳實踐建議

【導讀】go 語言實戰踩坑經驗!本文詳細介紹了實際項目開發中的實用規則。在開發中遵守規範也是保持良好團隊合作的必要操作,一起來學習吧!

一. 介紹

每種語言都會有基本的語言規範,本文將會介紹 Go 語言實戰建議 Practical Go: Real world advice for writing maintainable Go programs (https://dave.cheney.net/practical-go/presentations/qcon-china.html#_introduction)

二. 指導原則

Go 語言有以下 3 點基本指導原則

  1. 簡單性: 簡單性是 Go 語言的最高目標,無論我們編寫什麼程序,我們都應該同意這一點它們很簡單。很多情況下我們都害怕遇到一個問題就是 我不懂這段代碼,不知如何修復,這會導致軟件複雜不可靠。

  2. 可讀性: 可讀性很重要,因爲所有軟件不僅僅是 Go 語言程序都是由人類編寫的,供他人閱讀。執行軟件的計算機則是次要的。代碼的讀取次數比寫入次數多。一段代碼在其生命週期內會被讀取數百次,甚至數千次。可讀性是能夠理解程序正在做什麼的關鍵,編寫可維護代碼的第一步是確保代碼可讀。

  3. 生產力: Go 程序員應該覺得他們可以通過 Go 語言完成很多工作。快速編譯是 Go 語言的一個關鍵特性,也是吸引新開發人員的關鍵工具,Go 語言編譯只需要幾秒鐘。Go 程序員相對於 C++ 來說不會花費整天的時間來調試不可思議的編譯錯誤。

三. 標識符

標識符是用來表示名稱的單詞,例如變量名稱、函數名稱、方法名稱、類型名稱、包名稱等等。
可讀性是良好代碼的定義質量,因此選擇好名稱對於 Go 代碼的可讀性至關重要。

  1. 標識符命名應該清晰而不是簡潔
  1. 標識符長度有以下要求
1  var p = 0
2  p += count
3
4
1  var userCount int
2
3
1  # 循環
2  for i, v := range items {}
3  # 函數、參數和返回值
4  func getUserCount(endTime int64) (int64) {}
5  # 包
6  package http
7
8
  1. 不要用變量類型命名你的變量
  1. 使用一致的命名方式
  1. 使用一致的聲明樣式
1    var players int        默認爲0
2    var things []*Thing    默認爲nil
3
4
1    players := 5
2    things := make([]*Thing, 0)
3
4
  1. 成爲團隊合作者,所有代碼都需要使用 gofmt 格式化

四. 註釋

註釋對Go語言程序的可讀性非常重要,註釋目的是如下 3 個。

  1. 註釋應該解釋其作用。

  2. 註釋應該解釋其如何做的。

  3. 註釋應該解釋其原因。

註釋的方式有以下幾種

  1. 文件註釋應該使用// Package xxxx 開頭並且註釋是誰在什麼時間點創建或更新
1// Package main ...
2// Created by chenguolin 2018-12-26
3
4
  1. 公共變量、常量、可見函數註釋應該使用//
 1    // AppName application name
 2    const AppName = "HTTP_SERVER"
 3
 4    // Users user count
 5    var Users map[string]int
 6
 7    // GetUserName get user name by id
 8    func GetUserName(id int64) string {}
 9
10

註釋應該滿足以下幾點要求

  1. 關於變量和常量的註釋應描述其內容而非其目的
1    // randomNumber determined from an unbiased die
2    const randomNumber = 6
3
4
1    // sizeCalculationDisabled indicates whether it is safe
2    // to calculate Types' widths and alignments. See dowidth. 
3    var sizeCalculationDisabled bool
4
5
  1. 公共符號始終要註釋
  1. 不要註釋不好的代碼,將它重寫
  1. 與其註釋一段代碼,不如重構它

五. 包的設計

一個好的Go語言包應該具有低程度的源碼級耦合,這樣隨着項目的增長,對一個包的更改不會跨代碼庫級聯。

  1. 一個好的包從它的名字開始
  1. 儘早 return 而不是深度嵌套
  1. 讓零值更有用

六. 項目結構

通常一個項目是一個 git 倉庫,每個項目都應該有一個明確的目的。您應該避免在一個包實現多個目的,這將有助於避免成爲公共庫。

httpserver爲例,看通用的 HTTP service 項目的結構如下。

 1httpserver
 2├──cmd
 3  ├──api
 4  ├──cron
 5  ├──processor
 6├──common
 7  ├──base62
 8  ...
 9├──config
10  ...
11├──context
12  ...
13├──docs
14  ...
15├──pkg
16  ...
17├──scripts
18  ...
19├──vendor
20  ...
21├──.gitlab-ci.yml
22├──Gopkg.lock
23├──Gopkg.toml
24├──README.md
25├──VERSION
26
27
  1. 考慮更少,更大的包
  1. 優先內部測試再到外部測試
  1. 確保 main 包內容儘可能的少

七. 函數設計

函數設計非常的重要,如果函數沒有設計好那會導致不可兼容的情況,導致程序維護性變差。

  1. 設計難以被誤用的 函數
 1    // 錯誤舉例
 2    func CopyFile(src, dest string) error {}
 3
 4    CopyFile("file1", "file2")
 5    CopyFile("file2", "file1")
 6    對於上面的函數調用,如果參數填錯會導致文件被意外copy
 7
 8    // 準確舉例
 9    type Source string
10    func (s *Source) Copy(dest string) error{}
11
12    file1.Copy(file2)
13    file2.Copy(file1)
14    上述這種使用方式則比較不容易出錯
15
16
  1. 不鼓勵使用 nil 作爲參數
  1. 首選可變參數函數而非 []T 參數
  1. 讓函數定義它們所需的行爲

  2. 空行來分解函數,讓代碼看起來更有層次感

八. 錯誤處理

  1. 通過消除錯誤來消除錯誤處理
  1. 錯誤只處理一次

九. 併發

Go 語言以channel以及select和go語句來支持併發。如果Go語言程序的main函數返回,無論程序在一段時間內啓動的其他goroutine在做什麼, Go語言程序會無條件地退出。

  1. 如果你的goroutine在得到另一個結果之前無法取得進展,那麼讓自己完成此工作而不是委託給其他goroutine會更簡單。

  2. 將併發性留給調用者

  1. 永遠不要啓動一個停止不了的 goroutine
  1. 只在 main.main 或 init 函數中的使用 panic

  2. 一旦我們開啓的所有goroutine都停止了, main.main 就會返回並且進程會乾淨地停止

  3. 每個 Goroutine 都需要有 Recover 機制,除非你允許程序 Crash

十. 工具

使用任何語言開發程序都需要有一個統一的規範,否則很容易造成風格不統一導致代碼混亂不可維護。使用 Golang 開發有幾個高效率工具

  1. gofmt Golang 的開發團隊制定了統一的官方代碼風格,並且推出了 gofmt 工具(gofmt 或 go fmt)來幫助開發者格式化他們的代碼到統一的風格。gofmt 是一個 cli 程序,會優先讀取標準輸入,如果傳入了文件路徑的話,會格式化這個文件,如果傳入一個目錄,會格式化目錄中所有. go 文件,如果不傳參數,會格式化當前目錄下的所有. go 文件。go fmt 命令,go fmt 命令是 gofmt 的簡單封裝。
    常用的命令爲 go list ./... | xargs -n 1 gofmt -l -w

  2. go vet go vet 就是 golang 中提供的語法檢查工具, 可以讓我檢查出 package 或者源碼文件中一些隱含的錯誤,規範我們的項目代碼。
    常用的命令爲 go vet ./...

  3. golint golint 是用來檢測 Golang 代碼規範的,不同於 gofmt 和 go vet。golint 只是用於代碼規範檢查
    常用的命令爲 go list ./... | xargs -n 1 golint

轉自:陳國林

鏈接:https://blog.csdn.net/chenguolinblog/article/details/90665174

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/DOSj9aVvtQGAnjmUEo7LyA