Question
I'm learning Go, and I find it frustrating that the compiler does not allow unused variables or imported packages.
This slows me down during development. For example, I may want to import a package now and use it later, or temporarily comment out code while testing something. In these cases, the compiler reports errors such as variables being declared but not used.
Is there a way to disable or avoid this check in Go?
Short Answer
By the end of this page, you will understand why Go rejects unused variables and imports, why this rule exists, and how developers usually work with it in practice. You will also learn the correct ways to temporarily silence these errors during development without fighting the language.
Concept
In Go, unused local variables and unused imports are compile-time errors. This is a deliberate language design choice.
The goal is to keep code clean, readable, and maintainable:
- Unused variables often mean incomplete logic, old code, or mistakes.
- Unused imports add noise and can hide what the file actually depends on.
- Failing early helps catch problems before they become harder to notice.
Unlike some languages that only show warnings, Go treats these cases as errors. That means you usually cannot compile code until they are resolved.
A few important details:
- Unused local variables cause an error.
- Unused imports cause an error.
- Package-level variables can behave differently depending on context, but in day-to-day Go code, the most common issue is with local variables and imports.
- There is no normal compiler flag to globally disable this rule for regular Go development.
This matters in real programming because Go prefers a strict, predictable workflow. The language encourages you to keep files in a compilable state as you work. Instead of disabling the check, Go developers usually use small temporary techniques to satisfy the compiler while iterating.
Common temporary approaches include:
- Assigning a variable to the blank identifier:
_ = value - Importing a package with the blank identifier for side effects only:
import _ "package/name" - Removing the import until you actually need it
- Commenting out the declaration itself, not just its usage
So the short answer is: No, Go does not provide a standard way to turn this check off. The normal approach is to write code in a way that keeps the compiler happy while you develop.
Mental Model
Think of the Go compiler like a tidy teammate reviewing your desk.
- If you put a tool on the desk and never touch it, your teammate asks: Why is this here?
- If you bring a book into the room and never open it, your teammate asks: Why did you bring it?
In Go:
- A variable is like a tool you said you needed.
- An import is like a book you brought into the file.
If you are not using them, Go assumes something is unfinished, accidental, or unnecessary.
The blank identifier _ is like telling the compiler: Yes, I know this exists, and I am intentionally discarding it for now.
Syntax and Examples
Core syntax
Unused variable causes an error
package main
import "fmt"
func main() {
name := "Alice"
fmt.Println("Hello")
}
name is declared but never used, so Go reports an error.
Temporary fix with the blank identifier
package main
import "fmt"
func main() {
name := "Alice"
_ = name
fmt.Println("Hello")
}
This tells the compiler that you are intentionally ignoring name.
Unused import causes an error
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println("Hello")
}
Step by Step Execution
Consider this example:
package main
import "fmt"
func main() {
count := 10
_ = count
fmt.Println("Done")
}
Step by step:
- The program starts in
main. count := 10creates a local variable namedcount._ = countreads the variable and assigns it to the blank identifier.- The blank identifier discards the value.
- Because
countwas used, the compiler is satisfied. fmt.Println("Done")printsDone.
If you remove this line:
_ = count
then the compiler sees that count was declared but never used, and compilation fails.
Now compare with an unused import:
package main
import (
)
{
fmt.Println()
}
Real World Use Cases
This rule appears constantly in everyday Go development.
Common situations
- Refactoring code: you remove one line and suddenly an import is no longer needed.
- Debugging: you create a temporary variable to inspect a value.
- Building a feature step by step: you add a package import before writing the logic that uses it.
- Commenting out code during testing: this may leave variables or imports behind.
Real examples
1. API handler development
You start writing a JSON API handler and import encoding/json, but you have not yet added the response logic. Go will reject the unused import until you use it or remove it.
2. Database setup
Some database drivers are intentionally imported for side effects:
import _ "github.com/lib/pq"
This is a valid and common pattern.
3. Temporary debugging
result := calculateTotal(items)
_ = result
This can be a temporary step while you are building the next part of the function.
4. Incremental coding
Many Go developers write small compilable steps instead of sketching large amounts of unfinished code in one file. This fits the language's strict compile rules.
Real Codebase Usage
In real Go codebases, developers usually do not try to disable unused checks. Instead, they adopt workflows and patterns that work with the compiler.
Common patterns
Guarded incremental development
Write a small piece, compile it, then add the next piece. This keeps the codebase stable and avoids piles of unused declarations.
Remove and re-add imports automatically
Developers often rely on tools such as goimports, which automatically removes unused imports and adds missing ones.
Temporary blank identifier usage
During refactoring, it is common to temporarily write:
_ = value
But this is usually short-lived, not something left in finished code.
Side-effect imports
Packages that register drivers, metrics exporters, or plugins may be imported like this:
import _ "example.com/plugin"
That is not a hack; it is an intentional Go pattern.
Validation and early cleanup
When developers delete logic, they also clean up:
- old imports
- temporary variables
- commented-out code that is no longer needed
Team practices
In shared projects, this rule is helpful because it:
- reduces dead code
- makes imports reflect actual dependencies
Common Mistakes
1. Expecting a compiler option to disable the check
Many beginners look for a flag to turn off unused variable or import errors.
go build -ignore-unused
That is not a normal Go option.
Avoid this mistake: assume the check is part of the language workflow and use the standard workarounds instead.
2. Keeping unused imports around "for later"
Broken example:
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("hello")
}
time is unused.
Fix: remove it now and re-add it later, or let goimports manage it.
3. Confusing _ = value with real logic
userID := 42
_ = userID
This only silences the compiler. It does not perform useful work.
Avoid this mistake: treat _ = value as temporary unless discarding the value is truly intentional.
Comparisons
| Concept | What it does | Common use | Good choice when |
|---|---|---|---|
| Unused variable error | Fails if a local variable is never used | Prevents dead or incomplete code | You want stricter correctness |
| Unused import error | Fails if an imported package is never referenced | Keeps dependencies clear | You want clean file-level dependencies |
Blank identifier _ = value | Marks a value as intentionally ignored | Temporary development aid | You need code to compile briefly |
Blank import import _ "pkg" | Imports a package only for side effects | Driver registration, plugin setup | The package's init() is the goal |
| Removing the code | Deletes unused declarations/imports |
Cheat Sheet
Quick rules
- Unused local variables cause a compile error.
- Unused imports cause a compile error.
- There is no standard Go setting to disable this globally.
- Remove unused code when possible.
- Use
_ = variableas a temporary workaround. - Use
import _ "package/path"only for intentional side effects.
Common fixes
Silence an unused variable temporarily
x := 10
_ = x
Remove an unused import
import "fmt"
Side-effect import
import _ "github.com/lib/pq"
When to use which
- Need it later? Remove it now and re-add it later.
- Temporarily unfinished function? Use
_ = valuebriefly. - Need package registration via
init()? Use a blank import.
Warning signs
These usually mean incomplete code:
FAQ
Can I disable the unused variable check in Go?
No, not in normal Go development. The language and toolchain are designed to reject unused local variables and imports.
Why does Go treat unused variables as errors instead of warnings?
Because unused values often indicate mistakes, unfinished refactoring, or dead code. Go prefers catching these early.
How do I temporarily keep a variable without using it?
Use the blank identifier:
_ = myVar
This tells the compiler you are intentionally ignoring it.
How do I keep an import that I only need for side effects?
Use a blank import:
import _ "some/package"
This is common for database drivers and plugin registration.
Is _ = value good practice?
As a temporary development step, yes. As a permanent habit, usually no unless discarding the value is intentional.
What tool helps with unused imports in Go?
goimports is commonly used. It can automatically add missing imports and remove unused ones.
Should I comment out code or delete it?
Usually delete it and rely on version control if needed later. Long commented-out sections often make code harder to read.
Mini Project
Description
Create a small Go program that simulates a work-in-progress command-line tool. The project demonstrates how unused variables and imports appear during development, and how to fix them in the Go way without disabling compiler checks.
Goal
Build a Go program that compiles cleanly while temporarily holding values for future use and using imports correctly.
Requirements
- Create a
mainfunction that prints a message to the console. - Declare at least one variable that is not part of the final output yet.
- Use the blank identifier to keep the program compiling.
- Include one normal import that is used.
- Add a commented example of a side-effect import for reference.
Keep learning
Related questions
Check if a Value Exists in a Slice in Go
Learn how to check whether a value exists in a slice in Go, and why Go has no Python-style `in` operator for arrays or slices.
Concatenating Slices in Go with append
Learn how to concatenate two slices in Go using append and the ... operator, with examples, pitfalls, and practical usage.
Convert String to Integer in Go: Idiomatic Parsing with strconv.Atoi
Learn the idiomatic way to convert a string to an int in Go using strconv.Atoi, with examples, errors, and common mistakes.