Go "declared and not used" / "imported and not used" - Fix in CI
By Daniel Zoghalchali·Latchkey
Go makes unused local variables and unused imports a compile error, not a warning. Code that runs fine after a quick edit locally can fail CI the moment a variable or import is left dangling.
What this error means
The build stops with declared and not used: x or "fmt" imported and not used, naming the exact identifier or import. Nothing compiles until the unused declaration is removed or used.
go build output
./main.go:8:2: "errors" imported and not used
./main.go:14:2: declared and not used: result
Diagnose it: toolchain, tags, or platform?
Go build failures that only appear in CI usually come from a different toolchain version, different build tags, or cross-compilation defaults that differ from your machine.
Terminal
go version
go env GOOS GOARCH CGO_ENABLED GOFLAGS GOTOOLCHAIN
# build exactly what CI builds, verbosely
go build -v ./... 2>&1 | tail -40
# CGO is the usual difference: on by default locally, often off in a slim CI image
CGO_ENABLED=0 go build ./...
Common causes
An unused local variable
A variable is declared (often left over from a refactor or a commented-out line) but never read. Go rejects it outright.
An unused import
An import remains after the code that used it was removed, or was added speculatively. Go forbids unused imports.
How to fix it
Let goimports clean it up
goimports removes unused imports and adds missing ones automatically.
Terminal
goimports -w .
go build ./...
Remove or use the declaration
Delete the unused variable, or use it where intended.
If you need the side effect of an import only, use a blank import (_ "package").
For an intentionally-ignored value, assign to _ instead of a named variable.
How to prevent it
Run gofmt/goimports on save and in CI.
Use a pre-commit hook that runs go build ./....
Assign unused-but-required values to _.
Frequently asked questions
What causes Go "declared and not used" / "imported and not used"?
There are 2 common causes: an unused local variable and an unused import. A variable is declared (often left over from a refactor or a commented-out line) but never read.
How do I fix Go "declared and not used" / "imported and not used"?
There are 2 fixes depending on which cause you have: let goimports clean it up and remove or use the declaration. Work through them in order, since the first is the most common.
What does Go "declared and not used" / "imported and not used" actually mean?
The build stops with declared and not used: x or "fmt" imported and not used, naming the exact identifier or import.
How do I stop Go "declared and not used" / "imported and not used" happening again?
Run gofmt/goimports on save and in CI. The prevention section lists 3 changes that keep it from recurring.