Editors and IDEs for Go
How to configure your editor for Go development using language server integration with gopls and essential formatting and linting tools
A plain text editor can open any .go file, but a properly configured Go development environment does far more. It catches errors before you run your code, navigates packages with a click, formats your source to a single community‑standard style, and points out subtle bugs as you type.
The Go ecosystem delivers all of this through a combination of editor extensions, the gopls language server, and standalone command‑line formatting and linting tools. Understanding how these pieces fit together turns an editor into a responsive Go workspace and eliminates the friction that beginners often experience when jumping between editor and terminal.
This section covers three layers of editor support: the most popular editor integrations, the language server that powers them, and the formatting and linting tools you’ll invoke daily.
Editor Support for Go
Every major programming editor can be turned into a productive Go environment by installing one extension. That extension acts as a client: it talks to gopls (the Go language server) using the Language Server Protocol, and it wires up commands for formatting, testing, and debugging.
The choice of editor is personal, but the Go‑specific setup follows the same pattern everywhere: install the editor’s Go extension, make sure gopls is available on your PATH, and let the extension handle the rest. The table below shows which extension to install for several widely used editors.
| Editor | Go Extension |
|---|---|
| VS Code | Go (by the Go team) |
| GoLand / IntelliJ IDEA | Go plugin (bundled with GoLand, available as plugin) |
| Vim / Neovim | vim-go or nvim-lspconfig with gopls |
| Emacs | go-mode with lsp‑mode or eglot |
gopls is the default:
Most modern Go extensions use gopls as the backend automatically. You rarely need to configure it manually. The extension will offer to install gopls for you the first time you open a Go file.
Quick‑Start for Three Editors
The steps differ slightly depending on which editor you use. Pick the tab that matches your editor.
Install the Go extension from the marketplace. Open any .go file and the extension will detect that gopls is missing and offer to install it. Confirm the installation.
Once gopls is present, you get code completion, hover documentation, jump‑to‑definition, and real‑time diagnostics. You can adjust behaviour in settings.json:
"go.toolsManagement.autoUpdate": true,
"go.lintTool": "golangci-lint",
"editor.formatOnSave": true,
"[go]": {
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
}
Verify the setup:
Open a Go file, type fmt.Println(, and pause. If a tooltip shows the function signature, gopls is working. If the editor suggests an import for "fmt" when you write fmt.Println in a new file, everything is wired up correctly.
Once the editor is talking to gopls, most of the Go‑specific magic happens through the language server. That makes it worth understanding what gopls actually does.
gopls – The Go Language Server
A language server is a standalone program that analyses your code and provides editor features through a standard protocol. Instead of every editor implementing Go support from scratch, editors implement the client side of the Language Server Protocol (LSP) and gopls acts as the server that understands Go semantics.
What gopls Provides
When you open a Go file and the editor shows a red squiggle under an unused variable, offers to auto‑import "net/http" as soon as you type http.Get, or lets you jump from a function call straight to its definition in another file, that is gopls at work.
Specifically, gopls delivers:
- Diagnostics – compile errors and
go vetwarnings as you type. - Code completion – suggestions scoped to the current package and its dependencies.
- Hover information – type signatures and documentation on mouse‑over.
- Go‑to‑definition and find‑references – navigation across the whole module.
- Code actions – quick fixes like “add missing import” or “remove unused parameter”.
- Formatting – integration with
gofmtandgoimports. - Signature help – parameter hints while typing function calls.
gopls replaces older tools:
Before gopls existed, editors relied on a collection of separate binaries: guru for navigation, godef for jump‑to‑definition, and gofmt for formatting. gopls consolidates all of that into a single server that stays running and maintains a live index of your code.
How gopls Works
When you first open a Go module, gopls reads the go.mod file, discovers the module’s packages, and parses them into in‑memory type information. As you edit a file, gopls re‑parses only the changed portions and re‑checks the affected packages.
It uses the standard go/packages library under the hood, which means it sees exactly what the go command sees. If your code compiles with go build, gopls understands it.
The server keeps a cache that makes subsequent operations fast, but it also means that sometimes a stale view lingers. Restarting the language server (usually available as an editor command) forces a full re‑index.
Installing gopls
Most editor extensions install gopls automatically. To install it manually, run:
go install golang.org/x/tools/gopls@latest
Make sure $GOPATH/bin (or $GOBIN) is on your PATH so that the editor can find the binary.
Version mismatch between gopls and Go:
Running an older gopls with a newer Go release can produce wrong diagnostics or fail to recognise new language features. Keep gopls up to date with go install golang.org/x/tools/gopls@latest whenever you upgrade your Go toolchain.
Common gopls Mistakes
A frequent confusion comes from running gopls outside the context of a Go module. If you open a folder that contains .go files but no go.mod, gopls will still work in a limited “GOPATH mode,” but you’ll miss module‑aware features. Creating a module with go mod init <name> resolves this.
Another recurring issue is a workspace with multiple modules. By default, gopls focuses on a single module root. To work on several modules simultaneously, use a go.work file:
go work init ./module-a ./module-b
This tells gopls to treat all listed modules as a single workspace, enabling cross‑module navigation and completion.
Code Formatting and Linting Tools
Go’s commitment to a single canonical style is enforced by tooling, not by convention. The gofmt command formats any Go source file into the standard layout. This removes entire categories of argument from code review.
gofmt – The Canonical Formatter
gofmt reformats Go source code to match the language specification’s formatting rules. It handles indentation, whitespace, line breaks around operators, and brace placement. Every Go developer uses it, so all Go code looks familiar regardless of who wrote it.
# Format a single file and print the result to stdout
gofmt main.go
# Rewrite the file in-place
gofmt -w main.go
# Format all .go files under the current directory
gofmt -w .
Many editors can invoke gofmt on save. With gopls, formatting is built in: enable "editor.formatOnSave": true in VS Code or :set gofmt_on_save=1 in vim‑go.
Always format before committing:
Unformatted code in a pull request is a strong signal that the author isn’t using standard tooling. Run gofmt -d . (which shows diffs) as a pre‑commit check to avoid this.
goimports – Imports Managed Automatically
goimports does everything gofmt does, plus it adds missing imports and removes unused ones. A file that uses fmt.Println but lacks import "fmt" will be fixed automatically when you run goimports -w main.go.
Install it with:
go install golang.org/x/tools/cmd/goimports@latest
Most editors allow you to set goimports as the formatter instead of plain gofmt. With gopls, “organize imports on save” is usually available as a code action, so you rarely need to run the command manually.
golangci-lint – The Unified Linter
While go vet catches obvious mistakes, a linter finds a broader class of issues: unused variables that go vet misses, style inconsistencies, known patterns that can be simplified, and potential bugs like copying a mutex by value.
golangci-lint bundles dozens of linters into one binary and runs them in parallel. It is the de‑facto standard for Go linting in CI pipelines and local development.
# Install
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
# Run on all packages in the current module
golangci-lint run ./...
Configure it with a .golangci.yml file at the root of your module. A minimal configuration for a new project might look like this:
linters:
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
Integrate linting early:
Running golangci-lint run ./... before every commit (or adding it as a pre‑commit hook) catches mistakes at the cheapest moment. Fixing an unused variable a week later in CI wastes time and context.
Connecting Formatting and Linting to Your Editor
Once these tools are installed, the editor should invoke them without extra configuration. For VS Code:
"go.formatTool": "goimports",
"go.lintTool": "golangci-lint",
"[go]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
}
For Vim with vim‑go:
let g:go_fmt_command = "goimports"
let g:go_lint_command = "golangci-lint"
A common beginner mistake is to install the tools but never enable “format on save.” The code compiles fine, but the formatting drifts. Enabling on‑save formatting ensures every file is always canonical without conscious effort.
Summary
Choosing an editor for Go is less about the editor itself and more about enabling the standard Go‑provided tools that sit behind it. Once gopls, gofmt, goimports, and a linter are active, the editor becomes a real‑time collaborator that warns you about mistakes and enforces idiomatic Go style before you even think about running go build.
The three layers covered here — editor integration, language server, and command‑line tools — are not separate concerns. They form a pipeline: the editor invokes gopls for diagnostics and navigation, and gopls in turn calls gofmt and goimports to format your code and manage imports. Adding golangci-lint as a separate step catches deeper problems that gopls alone might not surface.
If you are setting up your environment for the first time, follow the editor‑specific quick‑start, confirm that gopls shows diagnostics, and then turn on format‑on‑save with goimports. From that point forward, every Go file you write will be consistently formatted, correctly imported, and checked for common mistakes in real time.