Go lint 實踐

什麼是 lint?

靜態代碼分析。通俗地講,掃描源代碼,在不運行代碼的情況下,找出一些不規範的書寫方式以修正,
例如:if foo != false {...} 這樣的寫法顯然不如 if foo {} 好理解。
lint 程序掃描到這樣的 case 就可以給出提示,敦促開發者修正。下面是一些 lint 能檢測到的問題樣例:

fmt.Sprintf("%d""123")  // 錯誤
fmt.Sprintf("%s""123")  // 正確

for i, _ := range []int{1,2,3}{} // 錯誤
for i := range []int{1,2,3}{}    // 正確

a := make([]int, 0, 0)  // 錯誤
a := make([]int, 0)     // 正確

for _, v := range vs {          // 錯誤
    vectors = append(vectors, v)
}
vectors = append(vectors, vs...) // 正確

怎樣使用 lint?

  1. 執行掃描工作的程序是一個 bin 文件(稱爲 linter)。執行它就可以掃描項目源代碼給出提示。
    在 Go 生態內的 linter 有很多種,大部分是開源項目提供的,它們能掃描各式各樣的問題如 “廢棄代碼”,“冗餘的寫法”,“調用 deprecated api” 等。

  2. 經調研,在 Go 開發中最好的選擇不是使用某一種 linter,而是使用 Golangci-lint,他是一個開源的 linter 框架,作用類似手機上的應用市場,你可以通過配置選擇開啓五花八門的 linter,兼顧了使用靈活、功能強大。

  3. golangci-lint 的安裝使用見後文。

怎樣將 lint 集成到團隊工作流?

  1. 團隊工作中代碼倉庫是共享的,一個人跑 lint 沒用,需要大家遵循同一套 lint 規則。

  2. 具體辦法是,將 linter 的運行加入到 ci 流程中。
    任意開發 push 新代碼,都會觸發 lint,結果展示在 merge request 界面。如果存在 bad case,就不允許 merge 到 master 分支。這樣協作項目的代碼就能始終符合 lint 規範。

實踐介紹

背景: 團隊代碼庫,因爲歷史遺留小問題很多,肉眼排查不實際,想到引入 lint 解決該問題。
**ci 工具選擇:**linter 如上介紹使用 Golangci-lint。我們公司使用 Gitlab 作爲源碼管理平臺,ci 工具使用它提供的 Gitlabci。

下面是我自己做的準備工作,

  1. 安裝 Golangci-lint,命令如下,詳細說明可參考其 README
GOPATH_FIRST=$(echo $(go env GOPATH) | awk -F':' '{ print $1}')
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b ${GOPATH_FIRST}/bin v1.21.0
  1. 配置 Golangci-lint
    在項目根目錄下創建文件.golangci.yml,這個文件是 golangci-lint 的配置文件,可自定義 開啓/關閉哪些linter跳過某些文件跳過某些lint規則等。
    如無配置文件,Golangci-lint 會開啓一些預設 linter,這些在其文檔內有說明。

下面是我們組一個項目現在的.golangci.yml內容,

linters:
  disable-all: true  # 關閉其他linter
  enable:            # 下面是開啓的linter列表,之後的英文註釋介紹了相應linter的功能
    - deadcode      # Finds unused code
    # - errcheck      # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases
    - gosimple      # Linter for Go source code that specializes in simplifying a code
    - govet         # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
    - ineffassign   # Detects when assignments to existing variables are not used
    - staticcheck   # Staticcheck is a go vet on steroids, applying a ton of static analysis checks
    - structcheck   # Finds unused struct fields
    - typecheck     # Like the front-end of a Go compiler, parses and type-checks Go code
    - unused        # Checks Go code for unused constants, variables, functions and types
    - varcheck      # Finds unused global variables and constants
    - scopelint     # Scopelint checks for unpinned variables in go programs
    # - golint        # Carry out the stylistic conventions put forth in Effective Go and CodeReviewComments

linters-settings:
  govet:            # 對於linter govet,我們手動開啓了它的某些掃描規則
    check-shadowing: true
    check-unreachable: true
    check-rangeloops: true
    check-copylocks: true
  1. 運行 linter / 修正錯誤
    在項目根目錄下運行golangci-lint run
    該命令會加載.golangci.yml(如有),執行 lint。如代碼有問題,命令行會輸出錯誤提示,包括犯錯地點、修正方法,有時 linter 提示會比較含糊,拿關鍵字 google 一下能找到詳細說明

  1. 推廣
    爲做到平滑的推廣 lint,在操作時有下面的實踐
  1. ** 與 gitlabci 集成,** 走到這裏 lint 工具的準備就 ok 了,下面要將它和 ci 工具銜接在一起,

  2. 參考 Gitlabci 文檔,安裝 gitlabci runner

  3. 將它和 gitlab project 綁定在一起。自行安裝 gitlab runner 有點複雜,我們公司的工程效率團隊提供了公用的 docker runner,我這裏只要做好綁定就行。

  4. 在項目根目錄下創建一個名爲.gitlab-ci.yml的配置文件,這樣每當 push 代碼時,gitlab 檢測到有該文件,就會觸發 runner 執行 ci。我的.gitlab-ci.yml文件內容如下

image: registry.company.cn/ee/go:1.12.9-4

stages:
  - qa

lint:
  stage: qa
  script:
    - golangci-lint runGitLab CI/CD | GitLabimage: registry.company.cn/ee/go:1.12.9-4

stages:
  - qa

lint:
  stage: qa
  script:
    - golangci-lint run

轉自:夏路

zhuanlan.zhihu.com/p/143567949

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