gopls/v0.16.0

go install golang.org/x/tools/gopls@v0.16.0-pre.1

This release includes several features and bug fixes, and is the first version of gopls to support Go 1.23. To install it, run:

New support policy; end of support for Go 1.19 and Go 1.20

TL;DR: We are narrowing gopls' support window, but this is unlikely to affect you as long as you use at least Go 1.21 to build gopls. This doesn‘t affect gopls’ support for the code you are writing.

This is the last release of gopls that may be built with Go 1.19 or Go 1.20, and also the last to support integrating with go command versions 1.19 and 1.20. If built or used with either of these Go versions, it will display a message advising the user to upgrade.

When using gopls, there are three versions to be aware of:

  1. The gopls build go version: the version of Go used to build gopls.
  2. The go command version: the version of the go list command executed by gopls to load information about your workspace.
  3. The language version: the version in the go directive of the current file‘s enclosing go.mod file, which determines the file’s Go language semantics.

This gopls release, v0.16.0, is the final release to support Go 1.19 and Go 1.20 as the gopls build go version or go command version. There is no change to gopls' support for all language versions--in fact this support has somewhat improved with the addition of the stdversion analyzer (see below).

Starting with gopls@v0.17.0, which will be released after Go 1.23.0 is released in August, gopls will only support the latest version of Go as the gopls build go version. However, thanks to the forward compatibility added to Go 1.21, any necessary toolchain upgrade should be handled automatically for users of Go 1.21 or later, just like any other dependency. Additionally, we are reducing our go command version support window from 4 versions to 3. Note that this means if you have at least Go 1.21 installed on your system, you should still be able to go install and use gopls@v0.17.0.

We have no plans to ever change our language version support: we expect that gopls will always support developing programs that target any Go version.

By focusing on building gopls with the latest Go version, we can significantly reduce our maintenance burden and help improve the stability of future gopls releases. See the newly updated support policy for details. Please comment on issue #65917 if you have concerns about this change.

Configuration Changes

  • The experimental “allowImplicitNetworkAccess” setting is deprecated (but not yet removed). Please comment on https://go.dev/issue/66861 if you use this setting and would be impacted by its removal.

New features

Go 1.23 support

This version of gopls is the first to support new Go 1.23 language features, including range-over-func iterators and support for the godebug directive in go.mod files.

Integrated documentation viewer

Gopls now offers a “Browse package documentation” code action that opens a local web page displaying the generated documentation for the current Go package in a form similar to https://pkg.go.dev. The page will be initially scrolled to the documentation for the declaration containing the cursor. Use this feature to preview the marked-up documentation as you prepare API changes, or to read the documentation for locally edited packages, even ones that have not yet been saved. Reload the page after an edit to see updated documentation.

TODO: demo in VS Code.

Clicking on the source-code link associated with a declaration will cause your editor to navigate to the declaration.

TODO: demo of source linking.

Editor support:

(eglot--code-action eglot-code-action-doc "source.doc")

(defalias 'go-doc #'eglot-code-action-doc
  "Browse documentation for the current Go package.")
  • TODO: test in vim, neovim, sublime, helix.

Browse free symbols

Gopls offers another web-based code action, “Browse free symbols”, which displays the free symbols referenced by the selected code.

A symbol is “free” if it is referenced within the selection but declared outside of it. The free symbols that are variables are, in effect, the set of parameters that would be needed if the block were extracted into its own function in the same package.

Even when you don't intend to extract a block into a new function, this information can help you to tell at a glance what names a block of code depends on.

Each dotted path of identifiers (such as file.Name.Pos) is reported as a separate item, so that you can see which parts of a complex type are actually needed.

The free symbols of the body of a function may reveal that only a small part (a single field of a struct, say) of one of the function's parameters is used, allowing you to simplify and generalize the function by choosing a different type for that parameter.

  • TODO screenshot

  • VS Code: use the Source action > Browse free symbols menu item.

  • Emacs: requires eglot v1.17. You may find this go-doc function a useful shortcut:

(eglot--code-action eglot-code-action-freesymbols "source.freesymbols")

(defalias 'go-freesymbols #'eglot-code-action-freesymbols
  "Browse free symbols referred to by the current selection.")

TODO(dominikh/go-mode.el#436): add both of these to go-mode.el.

Browse assembly

Gopls offers a third web-based code action, “Browse assembly for f”, which displays an assembly listing of the function declaration enclosing the selected code, plus any nested functions (function literals, deferred calls). It invokes the compiler to generate the report. Reloading the page will update the report.

The machine architecture is determined by the “view” or build configuration that gopls selects for the current file. This is usually the same as your machine's GOARCH unless you are working in a file with go:build tags for a different architecture.

  • TODO screenshot

Gopls cannot yet display assembly for generic functions: generic functions are not fully compiled until they are instantiated, but any function declaration enclosing the selection cannot be an instantiated generic function.

unusedwrite analyzer

The new unusedwrite analyzer reports assignments, often to fields of structs, that have no effect because, for example, the struct is never used again:

func scheme(host string) string {
	u := &url.URL{
		Host:   host, // "unused write to field Host" (no need to construct a URL)
		Scheme: "https:",
	}
	return u.Scheme
}

This is at best an indication that the code is unnecessarily complex (for instance, some dead code could be removed), but often indicates a bug, as in this example:

type S struct { x int }

func (s S) set(x int) {
	s.x = x // "unused write to field x" (s should be a *S pointer)
}

stdversion analyzer

The new stdversion analyzer warns about the use of too-new standard library symbols based on the version of the go directive in your go.mod file. This improves our support for older language versions (see above), even when gopls is built with a recent Go version.

TODO: add a screenshot demonstrating the new diagnostics

Two more vet analyzers

The framepointer and sigchanyzer analyzers have long been part of go vet's suite, but had been overlooked in previous versions of gopls.

Henceforth, gopls will always include any analyzers run by vet.

Hover shows size/offset info, and struct tags

TODO: consolidate release notes related to Hover improvements.

Hovering over the identifier that declares a type or struct field now displays the size information for the type, and the offset information for the field. In addition, it reports the percentage of wasted space due to suboptimal ordering of struct fields, if this figure is 20% or higher. This information may be helpful when making space optimizations to your data structures, or when reading assembly code.

TODO: example hover image.

Hovering over a field with struct tags now also includes those tags.

TODO: example hover image

Hover and definition on doc links

Go 1.19 added support for links in doc comments, allowing the documentation for one symbol to reference another:

TODO: turn the code below into a VS Code screenshot of hover.

// Logf logs a message formatted in the manner of [fmt.Printf].
func Logf(format string, args ...any)

Gopls's Hover and Definition operations now treat these links just like identifiers, so hovering over one will display information about the symbol, and “Go to definition” will navigate to its declaration. Thanks to @rogeryk for contributing this feature.

Bugs fixed

Thank you to our contributors!

@guodongli-google for the unusedwrite analyzer. TODO: they're a xoogler; is there a more current GH account?

@rogeryk