还在犯低级错误?用 golangci-lint 配合 GitLab 进行代码静态检查!

背景

代码静态检查能检查出很多问题,这些问题可能在测试中也无法发现,只有某些极端条件下会触发,例如死锁、竞争条件,没有处理的 err 等;同时也能检查出代码中的 bad smell,能够优化代码质量,尽量减少技术债务。

思路

对于 Go,有比较现成的工具 golangci-lint。这是一个静态代码检查工具,能够配置多种 lint 规则,执行速度较快,适合在 ci 流程中运行。

接入的过程比较简单,通过 push 或者 merge request 触发 pipeline,然后运行静态代码检查,输出结果。

实操

GitLab CI

要实现在 push 或者 merge request 的时候触发 pipeline,首先需要定义一个 GitLab CI 流程。在项目里新建一个 .gitlab-ci.yml 文件,内容如下:

yaml 复制代码
default:
  image: leslieleung/gitlab-golangci-lint:v0.0.3

stages:
  - lint

workflow:
  rules:
    - if: "$CI_PIPELINE_SOURCE == 'push'

lint:
  stage: lint
  tags:
    - myrunner
  script:
    - export GOPROXY=https://goproxy.cn
    - golangci-lint run > report.xml
  artifacts:
    when: always
    reports:
      junit: report.xml
  allow_failure: true

首先,要求 runner 使用一个 docker 镜像来运行。在 CI 任务中,给 runner 配置环境可能比较麻烦,使用配好需要的软件的 docker 镜像是更好的选择。在这个 docker 镜像中,包含了 go 的运行环境和一个 golangci-lint 二进制文件。

然后定义一个 pipeline 需要运行的 stage(步骤),目前只需要进行一个 lint。接下来定义需要执行 workflow 的场景,使用rules.if,这里我设置了当发生 push 事件,且提交的分支不是 k8s 的自动构建分支时,运行这个 pipeline。

最后是定义每一个 job(步骤)。stage 和上面的 stages 对应,tags 用来标识要用来运行的 runner。重点介绍 script 和 artifacts 两部分。script 是在这个 job 中要运行的命令,因为只是执行代码检查,要运行的命令就比较简单。如果要进行构建等等,也可以在这里执行。artifacts 是一个用来上传上一步 script 产生的构建产物的空间,如果你在上一步构建了二进制之类的文件,可以使用 artifacts 发布产物,会在 pipeline 中产生一个下载页面。这里我们需要的是上一步 lint 出来的结果,因此我们选择artifacts.reports.junit,GitLab 自带了一个可视化 junit 单测结果的界面。

golangci-lint 配置

golangci-lint 自带了非常多的规则,可以根据项目的需要来启用。示例如下:

yaml 复制代码
run:
# 要跳过的目录,根据需要调整
  skip-dirs:
    - tests
    - docs
    - gen
# 当前项目的Go版本
  go: '1.19'
  timeout: 5m
  tests: false
  allow-parallel-runners: true
  modules-download-mode: readonly
  issues-exit-code: 0
output:
  format: junit-xml
linters:
  disable-all: true
  enable:
    - errcheck
    - govet
    - ineffassign
    - unused
    - gosimple
    - staticcheck
    - gocognit
    - nilerr
    - goconst
    - revive

这套配置比较简单,只包含了一些诸如未处理的 err、无效赋值、未使用的变量、过高复杂度等的静态检查,可以根据项目需要进行调整。

最终效果

在左侧 CI/CD -> Pipelines -> Tests 可以看到 lint 的结果,failures 数即为 linter 检测出的问题数。

相关推荐
老毛肚5 分钟前
Spring boot 特性和自写Reids组件
java·spring boot·后端
蝎子莱莱爱打怪7 分钟前
👍🏻👍🏻6年381颗芯片+韬定律,华为重新定义半导体,为什么还有人喷???
后端·面试·程序员
武子康1 小时前
Java-05 深入浅出 MyBatis动态SQL与参数拼接完全指南
java·spring boot·后端
Kir1to1 小时前
RabbitMQ消息可靠性三板斧
后端
ServBay1 小时前
Google I/O 2026 Antigravity 更新与 SDK
后端·ai编程·google io
cpp_learner1 小时前
QT 窗体遮罩
后端
mumu_wangwei2 小时前
【QFS】Golang自研的QFS分布式文件系统,QFS文件系统使用
开发语言·后端·golang
techdashen2 小时前
在 Rust 异步接口的丛林中生存:从同步 I/O 到手写异步状态机
开发语言·后端·rust
为思念酝酿的痛3 小时前
Linux线程
linux·服务器·后端
小江的记录本3 小时前
【Kafka核心】Kafka 3.0+ KRaft模式(替代ZooKeeper)核心原理与优势
java·数据库·分布式·后端·zookeeper·kafka·rabbitmq