Golang 專案的程式碼檢查(Linting)最佳實踐與 golangci-lint 設定指南 — 包含執行 Linter、設定 .golangci.yml、使用 nolint 指令抑制警告、解讀 Lint 輸出結果以及選擇 Linter。適用於設定 golangci-lint、詢問 Lint 警告或 nolint 抑制說明、建置程式碼品質工具鏈或挑選 Linter 時。當使用者提及 golangci-lint、go vet、staticcheck 或 revive 時亦可使用。
角色(Persona): 你是一名 Go 程式碼品質工程師。你將 Linting 視為開發工作流程中不可或缺的一等公民,而非事後才做的清理步驟。
運行模式:
- 設定模式(Setup mode) — 設定
.golangci.yml、挑選 Linter、啟用 CI:請按順序參閱「設定」與「開發工作流程」章節。 - 編碼模式(Coding mode) — 撰寫新的 Go 程式碼:當主 Agent 繼續實作功能時,啟動背景 Agent 僅針對修改過的檔案執行
golangci-lint run --fix;待其完成後再回報結果。 - 解讀/修復模式(Interpret/fix mode) — 閱讀 Lint 輸出、抑制警告、修復既有程式碼的問題:請從「解讀輸出結果」與「抑制 Lint 警告」開始;針對大規模的舊程式碼清理,請使用平行子 Agent(sub-agents)。
相依套件:
- golangci-lint:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
Go Linting
總覽
golangci-lint 是 Go 的標準 Lint 檢查工具。它整合了 100 多個 Linter 到單一執行檔中,可平行執行並提供統一的設定格式。請在開發過程中頻繁執行,且務必在 CI 中加入檢查。
每個 Go 專案都必須包含 .golangci.yml — 它是決定啟用哪些 Linter 以及如何設定的唯一真理來源(source of truth)。請參閱推薦設定檔,這是一個包含 48 個已啟用 Linter、可直接用於生產環境的完整設定。
快速參考
# 執行所有已設定的 Linter
golangci-lint run ./...
# 盡可能自動修復問題
golangci-lint run --fix ./...
# 格式化程式碼(golangci-lint v2+)
golangci-lint fmt ./...
# 僅執行單一 Linter
golangci-lint run --enable-only govet ./...
# 列出所有可用的 Linter
golangci-lint linters
# 輸出詳細資訊與耗時數據
golangci-lint run --verbose ./...
設定說明
推薦的 .golangci.yml 提供了一套包含 33 個 Linter 的生產級設定。關於詳細設定、Linter 分類及各 Linter 的說明,請參閱 Linter 參考指南 — 內容包含各 Linter 檢查的面向(正確性、風格、複雜度、效能、安全性)、全部 33+ 個 Linter 的詳細說明,以及各自的適用情境。
抑制 Lint 警告
請謹慎使用 //nolint 指令 — 務必先嘗試修復根本原因。
// 良好做法:指定具體的 Linter 並附上合理理由
//nolint:errcheck // 僅做觸發即忘(fire-and-forget)的日誌記錄,該錯誤無須處理
_ = logger.Sync()
// 不良做法:無理由的全面抑制
//nolint
_ = logger.Sync()
規則:
//nolint指令必須指定 Linter 名稱:使用//nolint:errcheck而非單純的//nolint//nolint指令必須包含理由說明註解://nolint:errcheck // 原因nolintlintLinter 會強制執行上述兩條規則 — 它會標註未指定名稱的//nolint以及缺乏原因的寫法- 絕不要在沒有極強理由的情況下抑制資安類 Linter(如 gosec、bodyclose、sqlclosecheck)
若需查閱完整的模式與範例,請參閱 nolint 指令指南 — 包含何時該抑制、如何撰寫理由說明、單行對比單一函式抑制的範例模式,以及反模式(anti-patterns)。
開發工作流程
- 每次做出重大變更後都應執行 Linter:
golangci-lint run ./... - 自動修復可修復的項目:
golangci-lint run --fix ./... - 在 Commit 前進行格式化:
golangci-lint fmt ./... - 在舊專案中漸進式導入:在
.golangci.yml中設定issues.new-from-rev,僅檢查新新增/修改的程式碼,隨後再逐步清理舊程式碼
Makefile 目標(推薦):
lint:
golangci-lint run ./...
lint-fix:
golangci-lint run --fix ./...
fmt:
golangci-lint fmt ./...
關於 CI 流水線設定(使用 golangci-lint-action 的 GitHub Actions),請參閱 samber/cc-skills-golang@golang-continuous-integration Skill。
解讀輸出結果
每個問題的輸出格式如下:
path/to/file.go:42:10: message describing the issue (linter-name)
括號中的 Linter 名稱會告訴你是哪一個 Linter 觸發了該警告。你可以利用此資訊:
- 在 參考指南 中查閱該 Linter,瞭解其檢查內容
- 若屬於誤報(false positive),可使用
//nolint:linter-name // 原因進行抑制 - 使用
golangci-lint run --verbose取得更多上下文與耗時資訊
常見問題
| 問題 | 解決方案 |
|---|---|
| "deadline exceeded" | 在 .golangci.yml 中設定或增加 run.timeout;golangci-lint v2 預設為無逾時限制(0) |
| 舊程式碼中的問題過多 | 設定 issues.new-from-rev: HEAD~1,僅針對新程式碼進行 Lint 檢查 |
| 找不到 Linter | 執行 golangci-lint linters 進行檢查 — 該 Linter 可能需要更新版本 |
| Linter 之間發生衝突 | 停用實用性較低的 Linter,並附上註解說明原因 |
| 升級後出現 v1 設定錯誤 | 執行 golangci-lint migrate 以轉換設定檔格式 |
| 在大型 Repo 中執行過慢 | 降低 run.concurrency,或使用 linters.exclusions.paths / formatters.exclusions.paths 排除特定路徑 |
平行化舊程式碼清理
在舊專案中引進 Lint 檢查時,最多可同時使用 5 個平行子 Agent(透過 Agent 工具)來同步修復獨立的 Linter 類別:
- 子 Agent 1:執行
golangci-lint run --fix ./...處理可自動修復的問題 - 子 Agent 2:修復資安類 Linter 發現的問題(bodyclose、sqlclosecheck、gosec)
- 子 Agent 3:修復錯誤處理相關問題(errcheck、nilerr、wrapcheck)
- 子 Agent 4:修復程式碼風格與格式化問題(gofumpt、goimports、revive)
- 子 Agent 5:修復程式碼品質問題(gocritic、unused、ineffassign)
交叉參考
- → 請參閱
samber/cc-skills-golang@golang-continuous-integrationSkill,了解搭配 golangci-lint-action 的 CI 流水線建置 - → 請參閱
samber/cc-skills-golang@golang-code-styleSkill,了解 Linter 所強制的程式碼風格規範 - → 請參閱
samber/cc-skills-golang@golang-securitySkill,了解 Linting 之外的 SAST 工具(gosec、govulncheck) - → 請參閱
samber/cc-skills-golang@golang-continuous-integrationSkill,了解如何在 CI 中依據這些規範進行自動化 AI 程式碼審查






