26

像 Awesome-Go 一样提升企业 Go 项目代码质量

 4 years ago
source link: https://www.tuicool.com/articles/EF77N3F
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1. Awesome-Go 项目

参与过 awesome-go 项目的 gopher 都知道,每个MR都必须满足它以下的要求:

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

  • [ ] 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 的主分支。

以下是我的两个合并进主分支的项目:

代码审查 Code Review ,程序员本能就是抵制的。我也不列外,但是很多事即使开始抵制,一旦尝试过,就再也停不下来。代码审查 Code Review 属此类。

通过参与 awesome-go 项目和实际的 Code Review 实践,可以得出:一个 Go 项目的优劣至少在编译期就可以作出初步判断,而判断标准就是以下两项:

  • 静态代码审查的通过率
  • 单元测试的代码覆盖率

2. 企业Go项目代码审查

同样在企业内部也遇到相同的问题,面对开发人员能力水平的参差不齐以及各种 Freestyle 的代码风格, 大大增加了企业 Go 项目的维护难度。指定一套标准规范,同时将其固化到 CI 过程,是非常必要的。

awesome-go 项目中采用的是开源的代码审查项目与集成服务,但这些服务仅用于开源项目。要移植到企业内部,需要一些必要的准备工作。分别找出 静态代码审查的通过率单元测试的代码覆盖率 替代方案。

2.1 代码审查神器: golangci-lint

通过收集筛选, 静态代码审查 工具选择 golangci-lint 项目。该项目的使用者包括了众多国际大厂: google、facebook、 IBM 等等。其可用性已经被充分的验证过了。

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 , 效果如图:

bVbtSDd?w=1704&h=1362

命令行效果,读者可以自己测试一下 cover github.com/x-mod/routine

2.2.3 CI集成

如何集成到 CI 流程,也很简单了,只需要做一件事: 设置好测试覆盖率的通过值,比对项目的测试覆盖率的值 。简单提供一下取值的脚本函数:

cover-value(){
  go test -cover $@ | awk '{print $5}' | awk -F. '{print $1}'
}

具体比较过程,以及参数配置等过程就交给读者了。急着上班,先写到这了。如果觉得有用就点赞吧,更多文章可以关注我的个人BLOG: GitDiG.com .

3 参考链接


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK