Gopls release v0.21.0 (expected Dec 2025)
Configuration changes
-
The new
newGoFileHeaderoption allows toggling automatic insertion of the copyright comment and package declaration in a newly created Go file. -
The default value of the
codelensessetting now includesrun_govulncheck: true, causing gopls to offer a “Run govulncheck” command associated with themoduledeclaration in a go.mod file. -
The experimental
vulnchecksetting now supports the enum value"Prompt", meaning that vulncheck can be triggered via a prompt; this is now the default. -
The new, experimental
renameMovesSubpackagessetting determines whether a rename package operation applies to subdirectories; see below for details.
Navigational features:
Hover can now report information about selected subexpressions (#69058). For example, selecting the region indicated below:
x[i].f()
~~~~
will report information about the subexpression x[i], such as its
type, constant value (if appropriate), and methods.
Previously, Hover would report only about x, i, or f.
This feature requires the client to supply an extra field in the
textDocumentPositionParams part of its LSP textDocument/hover
request: the standard struct has a single position of type
Position, but gopls can also handle a range field of type
Range that specifies the extent of the text selection.
(If supplied, it must enclose the position.)
The VS Code code extension already populates this field. We plan to use it across various requests, and to lobby for its adoption by the LSP standard.
Other features in brief:
- Definition now works for fields in doc links in comments (#75038).
- Hover adds navigation to doc links in hovers (golang/vscode-go#3827).
- Hover now reports information (size, etc) about embedded fields, not just their types (#75975).
- Folding Range now displays closing parens (#75229) and more ranges (#73735).
Analysis features
reflecttypefor analyzer
The new reflecttypefor analyzer modernizes calls to reflect.TypeOf
to use reflect.TypeFor when the runtime type is known at compile
time. For example:
reflect.TypeOf(uint32(0))
becomes:
reflect.TypeFor[uint32]()
newexpr analyzer
The newexpr analyzer finds declarations of and calls to functions
of this form:
func varOf(x int) *int { return &x }
use(varOf(123))
modernizing them when appropriate to use the new(expr) feature of Go 1.26:
//go:fix inline
func varOf(x int) *int { return new(x) }
use(new(123))
Such wrapper functions are widely used in serialization packages, for instance the proto.{Int64,String,Bool} helpers used with protobufs.
stditerators analyzer
The stditerators analyzer replaces loops of this form,
for i := 0; i < x.Len(); i++ {
use(x.At(i))
}
or their “range x.Len()” equivalent, by
for elem := range x.All() {
use(elem)
}
for various types in the standard library that now offer a modern iterator-based API.
stringscut analyzer
The stringscut analyzer modernizes various patterns of use of
strings.Index such as:
i := strings.Index(s, sep)
if i >= 0 {
use(s[i:])
}
by a call to strings.Cut, introduced in Go 1.25:
before, after, ok := strings.Cut(s, sep)
if ok {
use(after)
}
plusbuild analyzer
The plusbuild analyzer removes old-style +build build-tag comments
when they are redundant with the newer form:
//go:build linux
// +build linux
errorsastype analyzer
The errorsastype analyzer replaces calls to errors.As:
var myErr *MyError
if errors.As(err, &myErr) { ... }
by the more modern errors.AsType, when the type is known statically:
if myErr, ok := errors.AsType[*MyError](err) { ... }
unsafefuncs analyzer
The unsafefuncs analyzer replaces arithmetic such as:
unsafe.Pointer(uintptr(ptr) + uintptr(n))
where ptr is an unsafe.Pointer, by calls to unsafe.Add, added in Go 1.17.
unsafe.Add(ptr, n)
Miscellaneous
- The
minmaxmodernizer now removes user-defined min/max functions when they are redundant. - The
stringscutprefixmodernizer now handlesstrings.CutSuffixtoo. - The
yieldandnilnessanalyzers handle control-flow booleans more precisely. - The
printfanalyzer now checks calls to local anonymous printf-wrapper functions too. - The
staticchecksuite has been updated to v0.7.
Code transformation features
Generalized package renaming
The Rename operation, invoked on a package p declaration, now
prompts you to edit the entire package path. This allows you to choose
not just a new name for the package, but a new directory anywhere
within the same module. For example, you can rename example.com/foo
to example.com/internal/bar, and the tool will move files and update
imports as needed.
By default, subpackages are no longer moved with the renamed package.
Enable the new (experimental) renameMovesSubpackages setting if you
want subpackages to move too. (In due course, we will add LSP support
for dialogs so that the server can query the user’s intent
interactively.)
This feature requires client support for the LSP
textDocument/prepareRename operation.
Renaming from a doc link
The Rename operation now treats doc links like identifiers, so you can initiate a renaming from a doc link.
Model context protocol (MCP) features
The MCP server now supports the go_rename_symbol tool, which permits
an agent to rename a symbol based on its name (e.g. fmt.Println or
bytes.Buffer.WriteString). The tool uses the symbol index to resolve
the name to a declaration and then initiates a renaming.
The server also supports the gopls.vulncheck tool, allowing agents
to scan packages for security vulnerabilities.
Closed issues
The source files for this documentation can be found beneath golang.org/x/tools/gopls/doc.