--- title: "Gopls release v0.24.0 (Oct 2026)" --- In this release: - [commits](https://go.googlesource.com/tools/+log/refs/heads/gopls-release-branch.0.23..refs/heads/gopls-release-branch.0.24) - [issues closed](https://github.com/golang/go/milestone/440?closed=1) Key features are described below. Gopls now supports [v3.18](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification) of the Language Server Protocol. This release includes a number of improvements to support for Go assembly files, including Hover, DocumentHighlight, References, and "zero configuration" (automatic selection of appropriate build tags). ## Configuration changes The `memoryLimit` setting allows clients to set a soft memory limit on the gopls process using [runtime/debug.SetMemoryLimit](https://pkg.go.dev/runtime/debug#SetMemoryLimit). This feature is experimental. It may permit users to trade more CPU for lower steady state memory usage; but it may cause GC thrashing if set too low. The gopls server now enforces [`SemanticTokensClientCapabilities`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#semanticTokensClientCapabilities) fields: `TokenTypes` and `TokenModifiers`. The semantic token types and modifiers gopls returns are now limited to what these lists contain, so it's important that clients fully list their semantic token capabilities. The gopls UI settings [`semanticTokenTypes`](https://go.dev/gopls/settings#semantictokentypes-mapstringbool) and [`semanticTokenModifiers`](https://go.dev/gopls/settings#semantictokenmodifiers-mapstringbool) can still be used by users to further restrict these lists. Gopls' "zero-configuration" behavior, which causes it to automatically select appropriate OS/ARCH combinations to build the open Go source files, now respects any open Go assembly files too. ## Passive features Gopls now supports the Hover request in Go assembly files: hovering over a symbol reports the signature and doc comment of its Go declaration. ## Editing features **Hovering** over the `case` or `default` keyword in a **type switch** reveals any types handled by that case that are declared in the same package as the switch operand's interface type. Hovering over the `default` case may thus reveal unhandled types in a switch intended to be exhaustive. Information is displayed for a non-interface type case only if it is unreachable due to preceding clauses. **Hovering** over a package name definition, reference or import now renders doc links as links to their definition in code or pkgsite. e.g. \[TestA.FieldOne\] in the comment `// xyz uses [TestA.FieldOne]`. Gopls now supports the `textDocument/documentHighlight` request in Go assembly files: all occurrences of the symbol, label, or machine register under the cursor are highlighted within the enclosing TEXT function, with definitions classified as writes and references as reads. The `textDocument/references` request in Go assembly files now supports control labels and symbols that have no corresponding Go declaration. Completion items now report [`labelDetails`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_completion) to clients that advertise `completionItem.labelDetailsSupport`: `detail` holds the signature or the type of the item, and `description` holds the import path that accepting it adds to the file. Only an item that adds an import has a `description`, so a client can mark those items. ## Analysis features Gopls is now using staticcheck [v0.8.1](https://github.com/dominikh/go-tools/releases/tag/2026.2.1). ### `ptrtoerror` analyzer This new analyzer reports inconsistent use of a named type `E` and its pointer type `*E` as an error. Declaring `func (E) Error() string` causes both `E` and `*E` to implement `error`, so a package may inadvertently return `E{...}` in one place and `&E{...}` in another. This is a latent bug: a client that checks for the error using a type assertion or `errors.Is` must choose one of the two types, and the check silently fails whenever the error was created using the other form. The analyzer reports three kinds of problem: - Within the package that declares `E`, values of both `E` and `*E` are converted to `error`. The analyzer reports the type declaration and each conversion. - The declaring package consistently uses one form, but another package converts the other form to `error`. The analyzer reports the conversion in the other package and indicates where the declaring package uses the preferred form. - Both `E` and `*E` implement `error`, but the declaring package doesn't convert either one to `error`, so the intended form is unclear. The analyzer offers two alternative fixes that declare the intended form explicitly, either `var _ error = *new(E)` or `var _ error = (*E)(nil)`. ### `slicesclip` modernizer The new `slicesclip` modernizer suggests replacing a full slice expression of the form `x[:len(x):len(x)]`, which clips the capacity of a slice to its length, with the simpler and more readable `slices.Clip(x)`, added in Go 1.21. ### `importcomment` modernizer The new `importcomment` modernizer removes obsolete comments specifying the canonical import path of a package, such as `package foo // import "example.com/foo"`. The go command enforced these comments only in GOPATH mode; in module mode they are ignored. ### `reflecttypeassert` modernizer The new `reflecttypeassert` modernizer suggests replacing a two-valued type assertion on the result of `reflect.Value.Interface`, such as `x, ok := v.Interface().(T)`, with `x, ok := reflect.TypeAssert[T](v)`, added in Go 1.25, which avoids allocating an intermediate interface value. No fix is offered for single-valued assertions, which panic on failure whereas `reflect.TypeAssert` does not. ### `stringintconv` updates for Go 1.28 Go 1.28 rejects conversions `string(x)` where `x` is an integer other than `byte` or `rune` ([#3939](https://go.dev/issue/3939)). The `stringintconv` analyzer's first suggested fix now preserves the existing behavior exactly, using `string(rune(x))`, or `fmt.Sprintf("%c", x)` for types wider than 32 bits, since truncation to a rune could make an invalid code point valid; the second fix, `fmt.Sprintf("%d", x)`, formats the number as a decimal. The same two fixes are now offered as quick fixes for the type error reported in files using Go 1.28 or later. ## Code transformation features ### "Implement interface" supports generic interfaces The interactive "Add methods to implement an interface..." code action now supports generic interfaces. When the selected interface has type parameters, `gopls` prompts for a type argument for each type parameter and generates method stubs with the instantiated method signatures. ### Demo of interactive dialog support: "Slay the dragon" The LSP standard currently provides no way for the server to ask the client a question such as "where should I move this function?" or "should I proceed with this ambiguous operation?". In conjunction with the Dart IDE team, the Go team has designed and implemented an extension to the Language Server Protocol to enable [interactive dialogs](https://github.com/microsoft/language-server-protocol/issues/1164#issuecomment-5622362595). We are currently trying to get it adopted by the LSP standard and implemented in various popular client editors, and plan to use it for future interactive features. As a demonstration of the feature and a test case for client implementations, gopls now offers a "Slay the dragon" code action when you select a package-level variable named `dragonSlayer`. A dragon has been spotted near your code. What happens next is up to you! ### Improved inlining of deferred functions The "Inline call" refactoring improves inlining of calls to some functions that use `defer`.