「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
引子
“kovogo哥, 我怎么提交不了代码了”
没想到工作两年就已经进入哥字辈了, 往旁边一看旁边新来的小伙子正常对着屏幕发愁, 一看控制台的报错,哦原来是golangci-lint打回了提交, 原因是某一行的代码太长了超过了限制。
那么在提交代码对代码规范进行检查是怎么做到的? 这就需要我们来回顾一下githook的知识了。
githook
什么是githook?
一般来说只要是上了规模的软件/中间件/开源框架或多或少的会提供一些hook, 供开发人员使用。而这些hook的作用就是在这些框架/软件中引入开发人员编写代码, 从而改变软件的表现形式或行为逻辑。
而githook就是git是向开发者提供的在git执行重要的操作引入开发者的代码的功能,比如上文提到在commit时引入代码检查的功能就是通过githook实现的。
每个git仓库在初始化的时候, 都会在.git目录下创建一个hooks目录,用来存放开发人员自定义的hook脚本(shell脚本), 脚本文件名即hook名。
windows 环境安装git时会自带
git bash, 因此无需要担心脚本的兼容性
当hook脚本返回0时表示放行对应的操作, 返回非0值表示拒绝此操作。
每个程序在退出的时候都会有返回值, 该返回值通常用来表示程序是否执行成功.
在Linux shell中我们可以通过, $?来获取上一个程序的返回值.
如上图所示, 我们尝试访问一个不存在的路径, ls命令的返回值是2.
我们可以在.git/hooks中看到如下文件:
上图中.sample文件都是git官方提供的参考, 去掉.sample后缀该钩子就会起效, 记住: 文件名即钩子名
如果需要在提交代码时对代码进行检测,我们就需要为pre-commit钩子编写代码规范检测脚本。
更多详细信息可参见官方文档
golintci-lint
由于golint已经被谷歌抛弃不再维护了, 我们使用了golangci-lint对代码规范进行检查。
安装
golangci-lint官网给出的安装方式有两种:
- 二进制安装, 直接下载对应平台的可执行文件
- 如果版本小于
1.16使用go get下载源文件并编译安装, 大于1.16则使用go install
1 | shell复制代码# Go 1.16+ |
以windows平台为例, 我的golang版本是1.16.10
因此我们使用go install的方式进行安装
使用
使用run命令即可对目标目录的代码进行检测
1 | shell复制代码golangci-lint run [目录] |
使用-h可以查看run命令的更多帮助信息
1 | shell复制代码golangci-lint run -h |
值得注意的选项有:
--issues-exit-code代码检测失败返回的错误码, 默认是1-c, --config PATH用于定制代码检测项目的配置文件(yaml格式)--skip-files要跳过的文件--skip-dirs要跳过的目录--enable要启用的代码检测项目
定制代码检测
上文提到, 我们可以通过--config来定制代码检测项目的配置, 其格式如下:
1 | yaml复制代码linters-settings: |
更多信息参考官方文档
githook + golangci-lint
以windows平台为例, 我们新建一个项目
然后新建一个代码文件, 随便写点乱七八糟的代码:
1 | go复制代码func main() { |
golangci-lint检测到了Printf传了错误的参数
我们再往项目中里面加点有”坏味道”的代码, 如下所示:(示例来自cyclop项目的测试文件)
1 | go复制代码func T() { |
再次进行代码检测, 注意此时需要启用圈复杂度检测插件cyclop
如果我们想要让代码通过检测,就需要使用到上文提到的使用配置文件自定义代码检测项目了。
在项目中创建lint.yaml, 并编写配置项如下
1 | yaml复制代码linters-settings: |
再次运行并指定配置文件, 此时已不再提示圈复杂度过高
pre-commit hook
利用上文的知识,我们的pre-commit hook 脚本的逻辑如下所示:
- 检测是否安装golangci-lint, 如果没有则进行安装
- 运行golangci-lint对代码进行检测,如果检测失败返回1成功则返回0
1 | shell复制代码#!/bin/sh |
尝试对代码提交,运行效果如下图所示
本文转载自: 掘金