gopls: Navigation, Refactoring & Diagnostics
gopls is the official Go language server.
Search across all documentation pages
gopls is the official Go language server.
It turns your editor into a type-aware client: jump to definitions, rename symbols across packages, surface diagnostics, and apply fixes before you run go build.
gopls loads your module (or go.work workspace), type-checks packages incrementally, and answers LSP requests from the editor.
Navigation commands resolve through the type checker, so they respect imports, build tags, and generics.
Refactoring operations (rename, add import, extract function) edit the AST with type-checked patches rather than blind search-and-replace.
Diagnostics merge compiler errors from go/types with selected analyzers (unused variables, printf mistakes, and more).
Quick-reference recipe card - copy-paste ready.
Editor actions (names vary by IDE):
| Action | Typical shortcut | gopls method |
|---|---|---|
| Go to definition | F12 / Cmd+click | textDocument/definition |
| Find references | Shift+F12 | textDocument/references |
| Rename symbol | F2 | textDocument/rename |
| Organize imports | on save | textDocument/codeAction |
| Show diagnostics | automatic | textDocument/publishDiagnostics |
When to reach for this:
go build and vet-style issues early.Consider a small module:
// example.com/demo/internal/greet/greet.go
package greet
func Hello(name string) string {
return "hello, " + name
}// example.com/demo/cmd/app/main.go
package main
import (
"fmt"
"example.com/demo/internal/greet"
)
func main() {
fmt.Println(greet.Hello("world"))
}With gopls running at the module root:
greet.Hello in main.go opens greet.go on the function body.Hello lists main.go and any test files importing greet.Hello to Greet updates both files and adjusts import usage if the symbol moves packages (gopls may prompt or refuse if it would break visibility).fmt if you delete the println, adds missing imports when you reference new packages.What this demonstrates:
go run.go.mod or go.work).| Feature | Behavior |
|---|---|
| Definition | Jumps to declaring identifier; for interfaces, may offer type definition vs implementation |
| Implementation | Lists concrete types implementing an interface method |
| References | All identifier uses in scope of workspace, including tests |
| Document symbol | Outline of functions, types, and constants in current file |
| Workspace symbol | Fuzzy search across package-qualified names |
| Feature | Notes |
|---|---|
| Rename | Fails safely if shadowing or cross-module constraints would break |
| Add/import organize | Groups stdlib, third-party, local; applies goimports logic |
| Extract function | Lifts a block to a new function with inferred parameters |
| Generate tests | Scaffolds _test.go with table-driven stubs (editor dependent) |
gopls publishes diagnostics with severity (error, warning, hint).
Many include code actions: quick fixes for missing imports, suggested types, or trivial refactors.
Analyzer diagnostics approximate go vet and friends; they are not guaranteed to match every CI linter you enable later.
// build tags affect what gopls type-checks
//go:build integration
package myappAlign gopls.build.buildFlags or GOFLAGS with CI so tagged files do not flip between green locally and red in CI.
go.mod leaves gopls guessing; open the module or go.work directory. Fix: File → Open Folder on module root.go.work or a published version, cross-module rename may be incomplete. Fix: Add go.work for local multi-module edits.//go:build tags show as excluded or error in editor. Fix: Set buildFlags: ["-tags=integration"] in gopls settings to match CI.stringer outputs clutter navigation. Fix: Exclude *.pb.go from editor features or mark generated directories in gopls directory filters.golangci-lint run locally with the committed config.| Alternative | Use When | Don't Use When |
|---|---|---|
| Plain text search (rg) | Exploring comments, strings, or non-Go files | Renaming symbols or finding typed references |
go doc / pkg.go.dev | Reading public API docs offline | Navigating private internal/ across your module |
| IDE without gopls | Unsupported editor | You need accurate Go refactors (prefer gopls-backed clients) |
guru (legacy) | Maintaining very old workflows | Starting new projects (gopls superseded it) |
Run go mod download and ensure the folder opened is the module root.
Corporate proxies may block sumdb; set GOPROXY consistently with CI.
Only for modules in the same workspace or those your editor resolves as dependencies.
It will not rename consumers in repos you do not have open.
Definition jumps to the identifier's declaration site.
Type definition jumps to the underlying type for aliases and interface methods.
That is usually the editor running goimports or gopls code actions.
Disable format-on-save or organizeImports if it fights your flow.
Yes - navigation and rename understand type parameters and instantiated types in Go 1.18+.
Use "Go to implementations" (LSP textDocument/implementation) on the interface method or type.
Initial indexing type-checks many packages.
Use gopls memory limits, narrow workspace folders, and exclude vendor trees.
Yes - gopls check and gopls vulncheck exist for diagnostics without an IDE.
Daily editing still benefits from LSP integration.
No - they are editor hints.
The compiler remains authoritative; fix red squiggles that mirror build errors first.
Commit editor-agnostic team guidance (build tags, formatters).
Personal UI settings can stay local; share .vscode/settings.json only when the team standardizes on VS Code.
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 16, 2026