64. Professional workflow: linting, vuln checks, CI, and quality gates
64.1 Baseline commands
gofmt -w .
go test ./...
go test -race ./...
go vet ./...
go test -cover ./...
govulncheck ./...
staticcheck ./...
go vet and staticcheck are not style police; they catch real bugs:
wrong Printf formats, impossible type assertions, copied locks,
unreachable code, ineffective assignments, lost cancel functions.
64.2 A minimal GitHub Actions workflow
name: ci
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- run: go mod download
- run: gofmt -w . && git diff --exit-code
- run: go vet ./...
- run: go test ./...
- run: go test -race ./...
- run: govulncheck ./...
For large repos, run -race on the most important packages or nightly if
runtime is too high for every PR.
64.3 Keep generated and vendored code separate
internal/api/openapi.gen.go # generated; don't hand-edit
internal/api/handlers.go # hand-written
Generated code should have a reproducible command:
//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -o openapi.gen.go openapi.yaml
If nobody can regenerate it, the generated file is technical debt.