imported and not used: "package"
The immediate fix: delete the import line for the package you are not using. Go will not compile with unused imports.
Before (broken):
package main
import (
"fmt"
"os" // imported and not used
"strings" // imported and not used
)
func main() {
fmt.Println("hello")
}
After (fixed):
package main
import "fmt"
func main() {
fmt.Println("hello")
}
Why Go Enforces This
Unused imports are a compile error in Go for two reasons:
-
Build performance. Every imported package must be compiled and linked, even if none of its symbols are used. Requiring used imports keeps build times short, which matters at Go's scale (Google's codebase compiles in seconds partly because of this rule).
-
Code clarity. An unused import is noise. It makes readers wonder what the package is for and whether there is dead code. Enforcing removal keeps import blocks as a reliable map of a file's actual dependencies.
This rule applies only to named imports. The blank identifier _ is the escape hatch for packages imported solely for side effects.
Fix 1: Remove the Import
The simplest fix — just delete the import line.
Broken:
import (
"fmt"
"math/rand" // imported and not used
"time" // imported and not used
)
Fixed:
import "fmt"
For single-package imports, you can collapse to the single-line form. For multiple packages, use the grouped form with parentheses.
Fix 2: Actually Use the Package
If you added the import because you intended to use it, add the code that uses it.
Broken — import present but usage forgotten:
import (
"fmt"
"strings" // added for ToUpper, but forgot to call it
)
func greet(name string) {
fmt.Println("hello,", name)
}
Fixed:
import (
"fmt"
"strings"
)
func greet(name string) {
fmt.Println("hello,", strings.ToUpper(name))
}
Fix 3: Use the Blank Import _ for Side-Effect Imports
Some packages are imported purely for their init() function side effects — they register themselves with some global registry (database drivers, image format decoders, profiling tools). You never call any of their exported names directly.
In this case, use the blank identifier _ as the import alias. This tells the compiler: "I know I am not calling this package directly; I just want its init() to run."
Without blank import (broken):
import (
"database/sql"
"fmt"
"github.com/lib/pq" // imported and not used
)
func main() {
db, _ := sql.Open("postgres", "...")
fmt.Println(db)
}
Fixed with blank import:
import (
"database/sql"
"fmt"
_ "github.com/lib/pq" // registers the "postgres" driver via init()
)
func main() {
db, _ := sql.Open("postgres", "...")
fmt.Println(db)
}
Common packages that require blank imports:
| Package | Why |
|---|---|
_ "github.com/lib/pq" |
PostgreSQL driver for database/sql |
_ "github.com/go-sql-driver/mysql" |
MySQL driver for database/sql |
_ "github.com/mattn/go-sqlite3" |
SQLite driver for database/sql |
_ "image/png" |
Registers PNG decoder for image.Decode |
_ "image/jpeg" |
Registers JPEG decoder for image.Decode |
_ "net/http/pprof" |
Registers /debug/pprof HTTP handlers |
_ "golang.org/x/crypto/bcrypt" |
Not needed — bcrypt is used directly |
Fix 4: Use goimports for Automatic Management
goimports is the standard tool for automatically managing Go imports. It:
- Removes imports that are not used
- Adds imports for packages you reference but have not imported
- Groups and formats imports according to Go conventions
Install it:
go install golang.org/x/tools/cmd/goimports@latest
Run it on a file:
goimports -w main.go
Run it on all files in the project:
goimports -w .
Configure your editor to run goimports on save:
VS Code (.vscode/settings.json):
{
"go.formatTool": "goimports",
"editor.formatOnSave": true
}
GoLand: Settings → Go → Go Fmt → Goimports
Neovim (with gopls): gopls uses goimports automatically for code actions.
Once goimports is configured to run on save, you will never see the "imported and not used" error again during normal development.
Fix 5: Named Import Aliases
When you import a package with an alias, Go requires the alias to be used, not the original package name. A common mistake is importing with an alias and then using the original name.
Broken:
import (
j "encoding/json" // imported with alias 'j'
)
func main() {
json.Marshal(struct{}{}) // wrong: 'json' is not defined, use 'j'
}
Alternatively, the alias is unused if you import without alias and never call it:
import myfmt "fmt" // imported as myfmt
func main() {
fmt.Println("hi") // compile error: fmt undefined, myfmt imported and not used
}
Fixed:
import myfmt "fmt"
func main() {
myfmt.Println("hi") // use the alias, not the original name
}
Fix 6: The Dot Import (Use Sparingly)
A dot import (. "package") imports all exported names from the package into the current file's namespace, so you can call them without a qualifier. The package itself does not need to be referenced by name.
import . "fmt"
func main() {
Println("hello") // no fmt. prefix needed
}
This is generally discouraged because it makes it unclear where each identifier comes from. It is sometimes used in test files to avoid repetitive package prefixes. It does not cause an "imported and not used" error because the package names merge into the current namespace.
How Import Groups Should Be Organized
goimports enforces the standard Go import grouping convention:
import (
// Group 1: standard library
"fmt"
"os"
"strings"
// Group 2: external packages
"github.com/pkg/errors"
"golang.org/x/text/encoding"
// Group 3: internal packages (same module)
"mymodule/internal/config"
"mymodule/pkg/db"
)
Groups are separated by blank lines. goimports applies this automatically.
Related Guides
- Most Common Golang Errors and How to Fix Them
- Fix 'declared and not used' Error in Go
- Fix Golang 'undefined: function' Error
- go mod tidy Explained
FAQ
What is the difference between goimports and gofmt?
gofmt only formats Go source code (whitespace, indentation, brace placement). It does not touch imports. goimports does everything gofmt does, plus it manages import blocks — adding missing imports and removing unused ones. For most projects, configure goimports and you do not need gofmt separately.
I removed the import but now I get 'undefined' for the symbols I was using — what happened?
You removed an import that was actually needed. The compiler error changed from "imported and not used" to "undefined". Re-add the import and check whether you have code that uses the package. If the code is also gone, the import removal was correct. If the code is still there, add the import back.
Why does Go allow _ imports but not unused named imports?
The _ form is an explicit statement of intent: "I am importing this package only for its side effects, and I know I will not call any of its functions." Named imports without use are almost always mistakes — you either forgot to use the package or forgot to remove it. The _ form requires deliberate choice, which makes it acceptable as a special case.