Go Tooling Setup Basics
10 examples to get you started with gopls & Debugging - 7 basic and 3 intermediate.
Prerequisites
- Install Go 1.26.x or later from go.dev/dl.
- Create a module:
mkdir tooling-demo && cd tooling-demo && go mod init example.com/tooling-demo. - Ensure
$(go env GOPATH)/binis on yourPATHso installed tools are found.
go install golang.org/x/tools/gopls@latest
go install github.com/go-delve/delve/cmd/dlv@latest
go install golang.org/x/vuln/cmd/govulncheck@latest
go install honnef.co/go/tools/cmd/staticcheck@latestBasic Examples
1. Verify core tools are on PATH
Confirm the language server and debugger binaries resolve before configuring an editor.
which gopls dlv
gopls version
dlv versiongo installplaces binaries inGOPATH/bin(often~/go/bin).- Editors invoke
goplsby name; a missing PATH entry looks like "language server not found." - Pin versions in team docs when CI and laptops must match.
Related: Go Developer Tooling: LSP, Debugger, and Analyzers - how the pieces fit together
2. Minimal gopls settings for a module
Point gopls at your module root and enable formatting on save in VS Code-style settings.
{
"gopls": {
"ui.semanticTokens": true,
"formatting.gofumpt": true
},
"go.useLanguageServer": true
}- Open the folder that contains
go.mod, not a parent directory with unrelated modules. formatting.gofumptapplies stricter formatting thangofmtalone.- Other editors expose the same keys under their LSP client config.
Related: gopls: Navigation, Refactoring & Diagnostics - editor features powered by gopls
3. Run go vet on the module
go vet is built in and needs no extra install.
go vet ./...- Catches common mistakes (Printf format verbs, unreachable code, struct tags).
- Run in CI alongside tests for a zero-config baseline.
- golangci-lint can include vet checks, but
go vetstays useful in quick scripts.
Related: staticcheck & golangci-lint in CI - layering analyzers in CI
4. First staticcheck pass
staticcheck finds correctness and performance issues beyond vet.
staticcheck ./...- Install once with
go install honnef.co/go/tools/cmd/staticcheck@latest. - Start with default checks; add
-checksonly when you need to disable a specific rule temporarily. - Treat new findings as backfill work, not instant CI blockers on legacy repos.
Related: staticcheck & golangci-lint in CI - severity and baselines
5. Scan dependencies with govulncheck
Check whether known CVEs affect code you actually import.
govulncheck ./...- Uses the Go vulnerability database; no API key required.
- Output distinguishes "affected module present" from "vulnerable symbol reachable."
- Add to CI after
go testso module download is already warm.
Related: govulncheck for Dependency Vulnerabilities - triage and CI wiring
6. Debug a simple program with Delve
Start the debugger on main.go and break at program entry.
# main.go: package main with func main()
dlv debug .Inside the dlv REPL:
(dlv) break main.main
(dlv) continue
(dlv) next
(dlv) print x
dlv debugbuilds with debug symbols and starts the process under the debugger.- Use
continue,next, andsteplike gdb-style commands. quitends the session.
Related: Debugging with Delve - goroutines and remote attach
7. golangci-lint quick start
Run a bundled linter set with one command.
# install once
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
golangci-lint run ./...- Creates or uses
.golangci.ymlwhen you customize enabled linters. - Faster local feedback than enabling every analyzer by hand.
- Match CI config to the file committed in the repo root.
Related: staticcheck & golangci-lint in CI - config and adoption
Intermediate Examples
8. gopls multi-module workspace (go.work)
When developing a library and consumer together, use a workspace file.
go work init ./app ./lib
go work use ./libOpen the directory containing go.work in your editor so gopls resolves cross-module imports.
- Without
go.work, local replaces requirereplacedirectives ingo.mod. - gopls loads all modules listed in
go.workfor cross-references. - CI still builds each module; workspaces are primarily a local ergonomics tool.
Related: Go Developer Tooling: LSP, Debugger, and Analyzers - monorepo tooling model
9. Delve headless for IDE attach
Run Delve listening on a port so VS Code or GoLand attaches remotely.
dlv debug --headless --listen=:2345 --api-version=2 --accept-multiclient .- IDE launch configs point at
localhost:2345with API v2. - Useful for debugging tests or binaries with custom build flags.
- Do not expose the port publicly; it grants full process control.
Related: Debugging with Delve - remote and container attach
10. Seed a golangci-lint config for CI
Commit a minimal .golangci.yml so laptops and CI share rules.
run:
timeout: 5m
linters:
enable:
- govet
- staticcheck
- ineffassign
- misspell
issues:
max-issues-per-linter: 0
max-same-issues: 0- Start with a small enable list; expand after baseline cleanup.
max-issues-per-linter: 0fails the run on any finding - loosen during migration.- Pair with
govulncheckin a separate CI job for dependency CVEs.
Related: gopls & Analysis Tooling Best Practices - editor and CI hygiene
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).