像 Awesome-Go 同樣提高企業 Go 項目代碼質量

原文發佈於個人我的網站: GitDiG.com, 原文連接: 像 Awesome-Go 同樣提高企業 Go 項目代碼質量.

1. Awesome-Go 項目

參與過awesome-go項目的gopher都知道,每一個MR都必須知足它如下的要求:html

Make sure that you've checked the boxes below before you submit PR:git

  • [ ] I have added my package in alphabetical order.
  • [ ] I have an appropriate description with correct grammar.
  • [ ] I know that this package was not listed before.
  • [ ] I have added godoc link to the repo and to my pull request.
  • [ ] I have added coverage service link to the repo and to my pull request.
  • [ ] I have added goreportcard link to the repo and to my pull request.
  • [ ] I have read Contribution guidelines, maintainers note and Quality standard.

總結出來,就是兩項關鍵質量指標:程序員

這兩項指標都經過量化的數值對合並項目進行審查。只有知足了指標的閥值要求,你說起的MR纔會被合進awesome-go的主分支。github

如下是個人兩個合併進主分支的項目:golang

代碼審查 Code Review,程序員本能就是抵制的。我也不列外,可是不少事即便開始抵制,一旦嘗試過,就再也停不下來。代碼審查Code Review屬此類。web

經過參與awesome-go項目和實際的Code Review實踐,能夠得出:一個 Go 項目的優劣至少在編譯期就能夠做出初步判斷,而判斷標準就是如下兩項:bash

  • 靜態代碼審查的經過率
  • 單元測試的代碼覆蓋率

2. 企業Go項目代碼審查

一樣在企業內部也遇到相同的問題,面對開發人員能力水平的良莠不齊以及各類Freestyle的代碼風格, 大大增長了企業 Go 項目的維護難度。指定一套標準規範,同時將其固化到 CI 過程,是很是必要的。app

awesome-go項目中採用的是開源的代碼審查項目與集成服務,但這些服務僅用於開源項目。要移植到企業內部,須要一些必要的準備工做。分別找出靜態代碼審查的經過率單元測試的代碼覆蓋率替代方案。less

2.1 代碼審查神器: golangci-lint

經過收集篩選,靜態代碼審查工具選擇golangci-lint項目。該項目的使用者包括了衆多國際大廠: google、facebook、 IBM 等等。其可用性已經被充分的驗證過了。dom

2.1.1 審查分類

golangci-lint中,它內置了絕大部分Go項目須要使用的審查工具。如下就其內置工具作一下簡單的分類。分類可以幫助咱們快速定製出必要的審查工具,哪些是必要的,哪些是可選的一目瞭然。

該分類,還能夠經過如下命令查詢:

$: golangci-lint help linters
...
##內置Linters分類
Linters presets:
bugs: bodyclose, errcheck, gosec, govet, scopelint, staticcheck, typecheck
complexity: gocyclo, nakedret
format: gofmt, goimports
performance: bodyclose, maligned, prealloc
style: depguard, dupl, gochecknoglobals, gochecknoinits, goconst, gocritic, golint, gosimple, interfacer, lll, misspell, stylecheck, unconvert
unused: deadcode, ineffassign, structcheck, unparam, unused, varcheck

更詳細的工具使用說明,能夠直接跳轉到對應的項目頁進行查詢。

代碼BUG審查
  • bodyclose - checks whether HTTP response body is closed successfully
  • errcheck - Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases
  • gosec - Inspects source code for security problems
  • govet - Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
  • scopelint - Scopelint checks for unpinned variables in go programs
  • staticcheck - Staticcheck is a go vet on steroids, applying a ton of static analysis checks
  • typecheck - Like the front-end of a Go compiler, parses and type-checks Go code
代碼複雜度
  • gocyclo - Computes and checks the cyclomatic complexity of functions
  • nakedret - Finds naked returns in functions greater than a specified function length
代碼格式化
  • gofmt - Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
  • goimports - Goimports does everything that gofmt does. Additionally it checks unused imports
代碼性能審查
  • bodyclose - checks whether HTTP response body is closed successfully
  • maligned - Tool to detect Go structs that would take less memory if their fields were sorted
  • prealloc - Finds slice declarations that could potentially be preallocated
代碼風格審查
  • golint - Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes
  • stylecheck - Stylecheck is a replacement for golint
  • interfacer - Linter that suggests narrower interface types
  • unconvert - Remove unnecessary type conversions
  • dupl - Tool for code clone detection
  • goconst - Finds repeated strings that could be replaced by a constant
  • depguard - Go linter that checks if package imports are in a list of acceptable packages
  • misspell - Finds commonly misspelled English words in comments
  • lll - Reports long lines
  • gosimple - Linter for Go source code that specializes in simplifying a code
  • gocritic - The most opinionated Go source code linter
  • gochecknoinits - Checks that no init functions are present in Go code
  • gochecknoglobals - Checks that no globals are present in Go code
無用代碼審查
  • deadcode - Finds unused code
  • ineffassign - Detects when assignments to existing variables are not used
  • structcheck - Finds unused struct fields
  • unparam - Reports unused function parameters
  • unused - Checks Go code for unused constants, variables, functions and types
  • varcheck - Finds unused global variables and constants

2.1.2 推薦配置

linter具體功能分類,在進行ci的過程當中, 配置以下:

  • [x] 代碼BUG
  • [x] 代碼複雜度
  • [x] 代碼格式化
  • [x] 代碼性能
  • [ ] 代碼風格
  • [ ] 無用代碼

勾選是必選項,非勾選按實際狀況進行配置。具體如何配置,能夠參考 .golangci.example.yml

配置好配置文件後,確認配置,經過如下命令查詢當前項目配置.

# 項目目錄下查詢具體啓用的linters設置
$: golangci-lint linters

golangci-lint配置文件的查詢規則是:從當前目錄,逐次向上級目錄查詢

2.1.3 CI集成

集成到企業 Go 項目的 CI 中就很簡單,在每一個項目的構建過程當中,增長如下命令便可:

# 項目目錄下
$: golangci-lint run

2.2 測試覆蓋率審查

完成了靜態代碼審查的準備工做,如今看看測試代碼覆蓋率的方案。

2.2.1 測試覆蓋率

Go 1.2 版本就已經提供了代碼測試覆蓋率的工具。具體操做以下:

# 項目總體測試覆蓋率, 以 github.com/x-mod/routine 項目爲例
$: go test -cover github.com/x-mod/routine | awk '{print $4 " " $5}'
coverage: 83.0%

具體測試覆蓋率詳細信息,能夠經過命令行的方式也能夠經過網頁的方式查看,按https://dave.cheney.net提供的腳本,簡單修改後以下:

# 測試覆蓋率詳情
cover () {
  t=$(mktemp)
  go test $COVERFLAGS -coverprofile=$t $@ && go tool cover -func=$t && unlink $t
}

# 測試覆蓋率詳情 web方式查看
cover-web() {
  t=$(mktemp)
  go test $COVERFLAGS -coverprofile=$t $@ && go tool cover -html=$t && unlink $t
}

具體測試覆蓋率詳情cover-web github.com/x-mod/routine, 效果如圖:

圖片描述

命令行效果,讀者能夠本身測試一下 cover github.com/x-mod/routine

2.2.3 CI集成

如何集成到 CI 流程,也很簡單了,只須要作一件事: 設置好測試覆蓋率的經過值,比對項目的測試覆蓋率的值。簡單提供一下取值比較的腳本函數:

cover-val(){
  cover $@ | grep ^total | awk '{print $3}' | awk -F. '{print $1}'
}

cover-cmp(){
  cmp=$1
  shift
  val=$(cover-val $@)
  num=$(($val+0))
  if [ $cmp -gt  $num ]; then
    echo "coverage insufficient."
    return 1
  fi
  return 0
}

下面在CI過程直接就能夠增長相應的覆蓋率審查操做:

# 覆蓋率 > 60%
$: cover-cmp 60 github.com/x-mod/routine ; echo $?
0

# 覆蓋率 > 90%
$: cover-cmp 90 github.com/x-mod/routine ; echo $?
coverage insuffient.
1

# Go 項目路徑 
$: cover-cmp 60 ./...

具體腳本可參考: liujianping/oh-my-zsh/plugins/alias.
更多文章能夠關注個人我的BLOG: GitDiG.com.

3 參考連接

相關文章
相關標籤/搜索