gopls & Analysis Tooling Best Practices
Editor intelligence and CI analyzers should tell the same story: fast feedback while typing, authoritative checks before merge.
Search across all documentation pages
Editor intelligence and CI analyzers should tell the same story: fast feedback while typing, authoritative checks before merge.
These practices keep gopls, Delve, and linters aligned across laptops and pipelines.
.golangci.yml and CI YAML.go.work root in the editor, not a parent folder. gopls needs go.mod (or workspace) at the workspace root for correct imports and diagnostics.gopls and go versions current within team policy. Mismatches produce spurious errors or missing features.buildFlags or GOFLAGS so tagged files type-check the same locally and in pipelines.gofumpt when the team standardizes on it. Consistent formatting removes noise from diffs and review.dlv) alongside gopls for every backend engineer. Debugging goroutines is a core skill, not an escalation-only tool.dlv test for failing tests before adding println debugging. Break on the assertion line and inspect goroutine stacks.-ldflags="-s -w" on images you attach to..golangci.yml at the repo root and run the same config locally. Drift between laptop and CI erodes trust in lint jobs.go test ./..., go vet ./..., and govulncheck ./... on every PR. Tests catch behavior; vet and govulncheck catch distinct failure classes.new-from-rev) on brownfield repos. Zero-tolerance day one causes teams to disable CI.*.pb.go, vendor) from lint, not hand-written packages. Generated noise trains people to ignore findings.//nolint comments. Require linter name, ticket, and reviewer approval for exceptions.go/analysis analyzers only when objective. Subjective taste stays in the review guide until it is machine-checkable.analysistest before enabling in CI. Untested linters create false-positive churn.tools/ with the same review bar as production code. Linters are part of the product's quality surface.test, vet, golangci-lint, govulncheck). One Makefile or mage target beats tribal knowledge.They should overlap on compiler and high-value checks.
CI may run more analyzers - that is expected.
Align configs to minimize surprises.
go test, go vet, staticcheck (via golangci-lint), and govulncheck.
Add gosec and nilaway as the threat model requires.
Use issues.new-from-rev and fix packages incrementally.
Track burn-down like any other engineering chore.
CLIs still deadlock, mis-handle errors, and panic.
Delve remains valuable for any non-trivial concurrency or state.
When the same objective violation appears on many PRs and no upstream linter fits.
Keep the rule narrow and tested.
Run on every PR branch.
Main-only scans let vulnerabilities land before the first nightly.
Lint each module from its go.mod root or document a meta-script.
Share one .golangci.yml template across services where policies match.
Dependabot lacks Go-specific reachability.
Keep govulncheck as the authoritative Go module CVE gate.
Any LSP client with gopls is fine.
Standardize settings and PATH, not necessarily the IDE brand.
Point them to Go Tooling Setup Basics, commit editor settings samples, and provide a one-command make check.
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).
Reviewed by Chris St. John·Last updated Jul 18, 2026