# Gopls
> title: "Gopls: Advanced topics"
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/advanced.md
---
title: "Gopls: Advanced topics"
---
This documentation is for advanced `gopls` users, who may want to test
unreleased versions or try out special features.
## Installing unreleased versions
To get a specific version of `gopls` (for example, to test a prerelease
version), run:
```sh
$ go install golang.org/x/tools/gopls@vX.Y.Z
```
Where `vX.Y.Z` is the desired version.
### Unstable versions
To update `gopls` to the latest **unstable** version, use the following
commands.
```sh
# Create an empty go.mod file, only for tracking requirements.
cd $(mktemp -d)
go mod init gopls-unstable
# Use 'go get' to add requirements and to ensure they work together.
go get -d golang.org/x/tools/gopls@master golang.org/x/tools@master
go install golang.org/x/tools/gopls
```
## Working on the Go source distribution
If you are working on the [Go project] itself, the `go` command that `gopls`
invokes will have to correspond to the version of the source you are working
on. That is, if you have checked out the Go project to `$HOME/go`, your `go`
command should be the `$HOME/go/bin/go` executable that you built with
`make.bash` or equivalent.
You can achieve this by adding the right version of `go` to your `PATH`
(`export PATH=$HOME/go/bin:$PATH` on Unix systems) or by configuring your
editor.
To work on both `std` and `cmd` simultaneously, add a `go.work` file to
`GOROOT/src`:
```
cd $(go env GOROOT)/src
go work init . cmd
```
Note that you must work inside the `GOROOT/src` subdirectory, as the `go`
command does not recognize `go.work` files in a parent of `GOROOT/src`
(https://go.dev/issue/59429).
[Go project]: https://go.googlesource.com/go
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md
---
title: "Gopls: Analyzers"
---
Gopls contains a driver for pluggable, modular static
[analyzers](https://pkg.go.dev/golang.org/x/tools/go/analysis#hdr-Analyzer),
such as those used by [go vet](https://pkg.go.dev/cmd/vet).
Most analyzers report mistakes in your code;
some suggest "quick fixes" that can be directly applied in your editor.
Every time you edit your code, gopls re-runs its analyzers.
Analyzer diagnostics help you detect bugs sooner,
before you run your tests, or even before you save your files.
This document describes the suite of analyzers available in gopls,
which aggregates analyzers from a variety of sources:
- all the usual bug-finding analyzers from the `go vet` suite (e.g. `printf`; see [`go tool vet help`](https://pkg.go.dev/cmd/vet) for the complete list);
- a number of analyzers with more substantial dependencies that prevent them from being used in `go vet` (e.g. `nilness`);
- analyzers that augment compilation errors by suggesting quick fixes to common mistakes (e.g. `fillreturns`); and
- a handful of analyzers that suggest possible style improvements (e.g. `simplifyrange`).
To enable or disable analyzers, use the [analyses](settings.md#analyses) setting.
In addition, gopls includes the [`staticcheck` suite](https://staticcheck.dev/docs/checks).
When the [`staticcheck`](settings.md#staticcheck`) boolean option is
unset, slightly more than half of these analyzers are enabled by
default; this subset has been chosen for precision and efficiency. Set
`staticcheck` to `true` to enable the complete set, or to `false` to
disable the complete set.
Staticcheck analyzers, like all other analyzers, can be explicitly
enabled or disabled using the `analyzers` configuration setting; this
setting takes precedence over the `staticcheck` setting, so,
regardless of what value of `staticcheck` you use (true/false/unset),
you can make adjustments to your preferred set of analyzers.
## `QF1001`: Apply De Morgan's law
Available since
2021.1
Default: off. Enable by setting `"analyses": {"QF1001": true}`.
Package documentation: [QF1001](https://staticcheck.dev/docs/checks/#QF1001)
## `QF1002`: Convert untagged switch to tagged switch
An untagged switch that compares a single variable against a series of values can be replaced with a tagged switch.
Before:
switch {
case x == 1 || x == 2, x == 3:
...
case x == 4:
...
default:
...
}
After:
switch x {
case 1, 2, 3:
...
case 4:
...
default:
...
}
Available since
2021.1
Default: on.
Package documentation: [QF1002](https://staticcheck.dev/docs/checks/#QF1002)
## `QF1003`: Convert if/else-if chain to tagged switch
A series of if/else-if checks comparing the same variable against values can be replaced with a tagged switch.
Before:
if x == 1 || x == 2 {
...
} else if x == 3 {
...
} else {
...
}
After:
switch x {
case 1, 2:
...
case 3:
...
default:
...
}
Available since
2021.1
Default: on.
Package documentation: [QF1003](https://staticcheck.dev/docs/checks/#QF1003)
## `QF1004`: Use strings.ReplaceAll instead of strings.Replace with n == -1
Available since
2021.1
Default: on.
Package documentation: [QF1004](https://staticcheck.dev/docs/checks/#QF1004)
## `QF1005`: Expand call to math.Pow
Some uses of math.Pow can be simplified to basic multiplication.
Before:
math.Pow(x, 2)
After:
x * x
Available since
2021.1
Default: off. Enable by setting `"analyses": {"QF1005": true}`.
Package documentation: [QF1005](https://staticcheck.dev/docs/checks/#QF1005)
## `QF1006`: Lift if+break into loop condition
Before:
for {
if done {
break
}
...
}
After:
for !done {
...
}
Available since
2021.1
Default: off. Enable by setting `"analyses": {"QF1006": true}`.
Package documentation: [QF1006](https://staticcheck.dev/docs/checks/#QF1006)
## `QF1007`: Merge conditional assignment into variable declaration
Before:
x := false
if someCondition {
x = true
}
After:
x := someCondition
Available since
2021.1
Default: off. Enable by setting `"analyses": {"QF1007": true}`.
Package documentation: [QF1007](https://staticcheck.dev/docs/checks/#QF1007)
## `QF1008`: Omit embedded fields from selector expression
Available since
2021.1
Default: off. Enable by setting `"analyses": {"QF1008": true}`.
Package documentation: [QF1008](https://staticcheck.dev/docs/checks/#QF1008)
## `QF1009`: Use time.Time.Equal instead of == operator
Available since
2021.1
Default: on.
Package documentation: [QF1009](https://staticcheck.dev/docs/checks/#QF1009)
## `QF1010`: Convert slice of bytes to string when printing it
Available since
2021.1
Default: on.
Package documentation: [QF1010](https://staticcheck.dev/docs/checks/#QF1010)
## `QF1011`: Omit redundant type from variable declaration
Available since
2021.1
Default: off. Enable by setting `"analyses": {"QF1011": true}`.
Package documentation: [QF1011](https://staticcheck.dev/docs/checks/#)
## `QF1012`: Use fmt.Fprintf(x, ...) instead of x.Write(fmt.Sprintf(...))
Available since
2022.1
Default: on.
Package documentation: [QF1012](https://staticcheck.dev/docs/checks/#QF1012)
## `S1000`: Use plain channel send or receive instead of single-case select
Select statements with a single case can be replaced with a simple send or receive.
Before:
select {
case x := <-ch:
fmt.Println(x)
}
After:
x := <-ch
fmt.Println(x)
Available since
2017.1
Default: on.
Package documentation: [S1000](https://staticcheck.dev/docs/checks/#S1000)
## `S1001`: Replace for loop with call to copy
Use copy() for copying elements from one slice to another. For arrays of identical size, you can use simple assignment.
Before:
for i, x := range src {
dst[i] = x
}
After:
copy(dst, src)
Available since
2017.1
Default: on.
Package documentation: [S1001](https://staticcheck.dev/docs/checks/#S1001)
## `S1002`: Omit comparison with boolean constant
Before:
if x == true {}
After:
if x {}
Available since
2017.1
Default: off. Enable by setting `"analyses": {"S1002": true}`.
Package documentation: [S1002](https://staticcheck.dev/docs/checks/#S1002)
## `S1003`: Replace call to strings.Index with strings.Contains
Before:
if strings.Index(x, y) != -1 {}
After:
if strings.Contains(x, y) {}
Available since
2017.1
Default: on.
Package documentation: [S1003](https://staticcheck.dev/docs/checks/#S1003)
## `S1004`: Replace call to bytes.Compare with bytes.Equal
Before:
if bytes.Compare(x, y) == 0 {}
After:
if bytes.Equal(x, y) {}
Available since
2017.1
Default: on.
Package documentation: [S1004](https://staticcheck.dev/docs/checks/#S1004)
## `S1005`: Drop unnecessary use of the blank identifier
In many cases, assigning to the blank identifier is unnecessary.
Before:
for _ = range s {}
x, _ = someMap[key]
_ = <-ch
After:
for range s{}
x = someMap[key]
<-ch
Available since
2017.1
Default: off. Enable by setting `"analyses": {"S1005": true}`.
Package documentation: [S1005](https://staticcheck.dev/docs/checks/#S1005)
## `S1006`: Use 'for { ... }' for infinite loops
For infinite loops, using for { ... } is the most idiomatic choice.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"S1006": true}`.
Package documentation: [S1006](https://staticcheck.dev/docs/checks/#S1006)
## `S1007`: Simplify regular expression by using raw string literal
Raw string literals use backticks instead of quotation marks and do not support any escape sequences. This means that the backslash can be used freely, without the need of escaping.
Since regular expressions have their own escape sequences, raw strings can improve their readability.
Before:
regexp.Compile("\\A(\\w+) profile: total \\d+\\n\\z")
After:
regexp.Compile(`\A(\w+) profile: total \d+\n\z`)
Available since
2017.1
Default: on.
Package documentation: [S1007](https://staticcheck.dev/docs/checks/#S1007)
## `S1008`: Simplify returning boolean expression
Before:
if {
return true
}
return false
After:
return
Available since
2017.1
Default: off. Enable by setting `"analyses": {"S1008": true}`.
Package documentation: [S1008](https://staticcheck.dev/docs/checks/#S1008)
## `S1009`: Omit redundant nil check on slices, maps, and channels
The len function is defined for all slices, maps, and channels, even nil ones, which have a length of zero. It is not necessary to check for nil before checking that their length is not zero.
Before:
if x != nil && len(x) != 0 {}
After:
if len(x) != 0 {}
Available since
2017.1
Default: on.
Package documentation: [S1009](https://staticcheck.dev/docs/checks/#S1009)
## `S1010`: Omit default slice index
When slicing, the second index defaults to the length of the value, making s\[n:len(s)] and s\[n:] equivalent.
Available since
2017.1
Default: on.
Package documentation: [S1010](https://staticcheck.dev/docs/checks/#S1010)
## `S1011`: Use a single append to concatenate two slices
Before:
for _, e := range y {
x = append(x, e)
}
for i := range y {
x = append(x, y[i])
}
for i := range y {
v := y[i]
x = append(x, v)
}
After:
x = append(x, y...)
x = append(x, y...)
x = append(x, y...)
Available since
2017.1
Default: off. Enable by setting `"analyses": {"S1011": true}`.
Package documentation: [S1011](https://staticcheck.dev/docs/checks/#S1011)
## `S1012`: Replace time.Now().Sub(x) with time.Since(x)
The time.Since helper has the same effect as using time.Now().Sub(x) but is easier to read.
Before:
time.Now().Sub(x)
After:
time.Since(x)
Available since
2017.1
Default: on.
Package documentation: [S1012](https://staticcheck.dev/docs/checks/#S1012)
## `S1016`: Use a type conversion instead of manually copying struct fields
Two struct types with identical fields can be converted between each other. In older versions of Go, the fields had to have identical struct tags. Since Go 1.8, however, struct tags are ignored during conversions. It is thus not necessary to manually copy every field individually.
Before:
var x T1
y := T2{
Field1: x.Field1,
Field2: x.Field2,
}
After:
var x T1
y := T2(x)
Available since
2017.1
Default: off. Enable by setting `"analyses": {"S1016": true}`.
Package documentation: [S1016](https://staticcheck.dev/docs/checks/#S1016)
## `S1017`: Replace manual trimming with strings.TrimPrefix
Instead of using strings.HasPrefix and manual slicing, use the strings.TrimPrefix function. If the string doesn't start with the prefix, the original string will be returned. Using strings.TrimPrefix reduces complexity, and avoids common bugs, such as off-by-one mistakes.
Before:
if strings.HasPrefix(str, prefix) {
str = str[len(prefix):]
}
After:
str = strings.TrimPrefix(str, prefix)
Available since
2017.1
Default: on.
Package documentation: [S1017](https://staticcheck.dev/docs/checks/#S1017)
## `S1018`: Use 'copy' for sliding elements
copy() permits using the same source and destination slice, even with overlapping ranges. This makes it ideal for sliding elements in a slice.
Before:
for i := 0; i < n; i++ {
bs[i] = bs[offset+i]
}
After:
copy(bs[:n], bs[offset:])
Available since
2017.1
Default: on.
Package documentation: [S1018](https://staticcheck.dev/docs/checks/#S1018)
## `S1019`: Simplify 'make' call by omitting redundant arguments
The 'make' function has default values for the length and capacity arguments. For channels, the length defaults to zero, and for slices, the capacity defaults to the length.
Available since
2017.1
Default: on.
Package documentation: [S1019](https://staticcheck.dev/docs/checks/#S1019)
## `S1020`: Omit redundant nil check in type assertion
Before:
if _, ok := i.(T); ok && i != nil {}
After:
if _, ok := i.(T); ok {}
Available since
2017.1
Default: on.
Package documentation: [S1020](https://staticcheck.dev/docs/checks/#S1020)
## `S1021`: Merge variable declaration and assignment
Before:
var x uint
x = 1
After:
var x uint = 1
Available since
2017.1
Default: off. Enable by setting `"analyses": {"S1021": true}`.
Package documentation: [S1021](https://staticcheck.dev/docs/checks/#S1021)
## `S1023`: Omit redundant control flow
Functions that have no return value do not need a return statement as the final statement of the function.
Switches in Go do not have automatic fallthrough, unlike languages like C. It is not necessary to have a break statement as the final statement in a case block.
Available since
2017.1
Default: on.
Package documentation: [S1023](https://staticcheck.dev/docs/checks/#S1023)
## `S1024`: Replace x.Sub(time.Now()) with time.Until(x)
The time.Until helper has the same effect as using x.Sub(time.Now()) but is easier to read.
Before:
x.Sub(time.Now())
After:
time.Until(x)
Available since
2017.1
Default: on.
Package documentation: [S1024](https://staticcheck.dev/docs/checks/#S1024)
## `S1025`: Don't use fmt.Sprintf("%s", x) unnecessarily
In many instances, there are easier and more efficient ways of getting a value's string representation. Whenever a value's underlying type is a string already, or the type has a String method, they should be used directly.
Given the following shared definitions
type T1 string
type T2 int
func (T2) String() string { return "Hello, world" }
var x string
var y T1
var z T2
we can simplify
fmt.Sprintf("%s", x)
fmt.Sprintf("%s", y)
fmt.Sprintf("%s", z)
to
x
string(y)
z.String()
Available since
2017.1
Default: off. Enable by setting `"analyses": {"S1025": true}`.
Package documentation: [S1025](https://staticcheck.dev/docs/checks/#S1025)
## `S1028`: Simplify error construction with fmt.Errorf
Before:
errors.New(fmt.Sprintf(...))
After:
fmt.Errorf(...)
Available since
2017.1
Default: on.
Package documentation: [S1028](https://staticcheck.dev/docs/checks/#S1028)
## `S1029`: Range over the string directly
Ranging over a string will yield byte offsets and runes. If the offset isn't used, this is functionally equivalent to converting the string to a slice of runes and ranging over that. Ranging directly over the string will be more performant, however, as it avoids allocating a new slice, the size of which depends on the length of the string.
Before:
for _, r := range []rune(s) {}
After:
for _, r := range s {}
Available since
2017.1
Default: off. Enable by setting `"analyses": {"S1029": true}`.
Package documentation: [S1029](https://staticcheck.dev/docs/checks/#S1029)
## `S1030`: Use bytes.Buffer.String or bytes.Buffer.Bytes
bytes.Buffer has both a String and a Bytes method. It is almost never necessary to use string(buf.Bytes()) or \[]byte(buf.String()) – simply use the other method.
The only exception to this are map lookups. Due to a compiler optimization, m\[string(buf.Bytes())] is more efficient than m\[buf.String()].
Available since
2017.1
Default: on.
Package documentation: [S1030](https://staticcheck.dev/docs/checks/#S1030)
## `S1031`: Omit redundant nil check around loop
You can use range on nil slices and maps, the loop will simply never execute. This makes an additional nil check around the loop unnecessary.
Before:
if s != nil {
for _, x := range s {
...
}
}
After:
for _, x := range s {
...
}
Available since
2017.1
Default: on.
Package documentation: [S1031](https://staticcheck.dev/docs/checks/#S1031)
## `S1032`: Use sort.Ints(x), sort.Float64s(x), and sort.Strings(x)
The sort.Ints, sort.Float64s and sort.Strings functions are easier to read than sort.Sort(sort.IntSlice(x)), sort.Sort(sort.Float64Slice(x)) and sort.Sort(sort.StringSlice(x)).
Before:
sort.Sort(sort.StringSlice(x))
After:
sort.Strings(x)
Available since
2019.1
Default: on.
Package documentation: [S1032](https://staticcheck.dev/docs/checks/#S1032)
## `S1033`: Unnecessary guard around call to 'delete'
Calling delete on a nil map is a no-op.
Available since
2019.2
Default: on.
Package documentation: [S1033](https://staticcheck.dev/docs/checks/#S1033)
## `S1034`: Use result of type assertion to simplify cases
Available since
2019.2
Default: on.
Package documentation: [S1034](https://staticcheck.dev/docs/checks/#S1034)
## `S1035`: Redundant call to net/http.CanonicalHeaderKey in method call on net/http.Header
The methods on net/http.Header, namely Add, Del, Get and Set, already canonicalize the given header name.
Available since
2020.1
Default: on.
Package documentation: [S1035](https://staticcheck.dev/docs/checks/#S1035)
## `S1036`: Unnecessary guard around map access
When accessing a map key that doesn't exist yet, one receives a zero value. Often, the zero value is a suitable value, for example when using append or doing integer math.
The following
if _, ok := m["foo"]; ok {
m["foo"] = append(m["foo"], "bar")
} else {
m["foo"] = []string{"bar"}
}
can be simplified to
m["foo"] = append(m["foo"], "bar")
and
if _, ok := m2["k"]; ok {
m2["k"] += 4
} else {
m2["k"] = 4
}
can be simplified to
m["k"] += 4
Available since
2020.1
Default: on.
Package documentation: [S1036](https://staticcheck.dev/docs/checks/#S1036)
## `S1037`: Elaborate way of sleeping
Using a select statement with a single case receiving from the result of time.After is a very elaborate way of sleeping that can much simpler be expressed with a simple call to time.Sleep.
Available since
2020.1
Default: on.
Package documentation: [S1037](https://staticcheck.dev/docs/checks/#S1037)
## `S1038`: Unnecessarily complex way of printing formatted string
Instead of using fmt.Print(fmt.Sprintf(...)), one can use fmt.Printf(...).
Available since
2020.1
Default: on.
Package documentation: [S1038](https://staticcheck.dev/docs/checks/#S1038)
## `S1039`: Unnecessary use of fmt.Sprint
Calling fmt.Sprint with a single string argument is unnecessary and identical to using the string directly.
Available since
2020.1
Default: on.
Package documentation: [S1039](https://staticcheck.dev/docs/checks/#S1039)
## `S1040`: Type assertion to current type
The type assertion x.(SomeInterface), when x already has type SomeInterface, can only fail if x is nil. Usually, this is left-over code from when x had a different type and you can safely delete the type assertion. If you want to check that x is not nil, consider being explicit and using an actual if x == nil comparison instead of relying on the type assertion panicking.
Available since
2021.1
Default: on.
Package documentation: [S1040](https://staticcheck.dev/docs/checks/#S1040)
## `SA1000`: Invalid regular expression
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1000": true}`.
Package documentation: [SA1000](https://staticcheck.dev/docs/checks/#SA1000)
## `SA1001`: Invalid template
Available since
2017.1
Default: on.
Package documentation: [SA1001](https://staticcheck.dev/docs/checks/#SA1001)
## `SA1002`: Invalid format in time.Parse
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1002": true}`.
Package documentation: [SA1002](https://staticcheck.dev/docs/checks/#SA1002)
## `SA1003`: Unsupported argument to functions in encoding/binary
The encoding/binary package can only serialize types with known sizes. This precludes the use of the int and uint types, as their sizes differ on different architectures. Furthermore, it doesn't support serializing maps, channels, strings, or functions.
Before Go 1.8, bool wasn't supported, either.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1003": true}`.
Package documentation: [SA1003](https://staticcheck.dev/docs/checks/#SA1003)
## `SA1004`: Suspiciously small untyped constant in time.Sleep
The time.Sleep function takes a time.Duration as its only argument. Durations are expressed in nanoseconds. Thus, calling time.Sleep(1) will sleep for 1 nanosecond. This is a common source of bugs, as sleep functions in other languages often accept seconds or milliseconds.
The time package provides constants such as time.Second to express large durations. These can be combined with arithmetic to express arbitrary durations, for example 5 \* time.Second for 5 seconds.
If you truly meant to sleep for a tiny amount of time, use n \* time.Nanosecond to signal to Staticcheck that you did mean to sleep for some amount of nanoseconds.
Available since
2017.1
Default: on.
Package documentation: [SA1004](https://staticcheck.dev/docs/checks/#SA1004)
## `SA1005`: Invalid first argument to exec.Command
os/exec runs programs directly (using variants of the fork and exec system calls on Unix systems). This shouldn't be confused with running a command in a shell. The shell will allow for features such as input redirection, pipes, and general scripting. The shell is also responsible for splitting the user's input into a program name and its arguments. For example, the equivalent to
ls / /tmp
would be
exec.Command("ls", "/", "/tmp")
If you want to run a command in a shell, consider using something like the following – but be aware that not all systems, particularly Windows, will have a /bin/sh program:
exec.Command("/bin/sh", "-c", "ls | grep Awesome")
Available since
2017.1
Default: on.
Package documentation: [SA1005](https://staticcheck.dev/docs/checks/#SA1005)
## `SA1007`: Invalid URL in net/url.Parse
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1007": true}`.
Package documentation: [SA1007](https://staticcheck.dev/docs/checks/#SA1007)
## `SA1008`: Non-canonical key in http.Header map
Keys in http.Header maps are canonical, meaning they follow a specific combination of uppercase and lowercase letters. Methods such as http.Header.Add and http.Header.Del convert inputs into this canonical form before manipulating the map.
When manipulating http.Header maps directly, as opposed to using the provided methods, care should be taken to stick to canonical form in order to avoid inconsistencies. The following piece of code demonstrates one such inconsistency:
h := http.Header{}
h["etag"] = []string{"1234"}
h.Add("etag", "5678")
fmt.Println(h)
// Output:
// map[Etag:[5678] etag:[1234]]
The easiest way of obtaining the canonical form of a key is to use http.CanonicalHeaderKey.
Available since
2017.1
Default: on.
Package documentation: [SA1008](https://staticcheck.dev/docs/checks/#SA1008)
## `SA1010`: (*regexp.Regexp).FindAll called with n == 0, which will always return zero results
If n >= 0, the function returns at most n matches/submatches. To return all results, specify a negative number.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1010": true}`.
Package documentation: [SA1010](https://staticcheck.dev/docs/checks/#SA1010)
## `SA1011`: Various methods in the 'strings' package expect valid UTF-8, but invalid input is provided
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1011": true}`.
Package documentation: [SA1011](https://staticcheck.dev/docs/checks/#SA1011)
## `SA1012`: A nil context.Context is being passed to a function, consider using context.TODO instead
Available since
2017.1
Default: on.
Package documentation: [SA1012](https://staticcheck.dev/docs/checks/#SA1012)
## `SA1013`: io.Seeker.Seek is being called with the whence constant as the first argument, but it should be the second
Available since
2017.1
Default: on.
Package documentation: [SA1013](https://staticcheck.dev/docs/checks/#SA1013)
## `SA1014`: Non-pointer value passed to Unmarshal or Decode
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1014": true}`.
Package documentation: [SA1014](https://staticcheck.dev/docs/checks/#SA1014)
## `SA1015`: Using time.Tick in a way that will leak. Consider using time.NewTicker, and only use time.Tick in tests, commands and endless functions
Before Go 1.23, time.Tickers had to be closed to be able to be garbage collected. Since time.Tick doesn't make it possible to close the underlying ticker, using it repeatedly would leak memory.
Go 1.23 fixes this by allowing tickers to be collected even if they weren't closed.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1015": true}`.
Package documentation: [SA1015](https://staticcheck.dev/docs/checks/#SA1015)
## `SA1016`: Trapping a signal that cannot be trapped
Not all signals can be intercepted by a process. Specifically, on UNIX-like systems, the syscall.SIGKILL and syscall.SIGSTOP signals are never passed to the process, but instead handled directly by the kernel. It is therefore pointless to try and handle these signals.
Available since
2017.1
Default: on.
Package documentation: [SA1016](https://staticcheck.dev/docs/checks/#SA1016)
## `SA1017`: Channels used with os/signal.Notify should be buffered
The os/signal package uses non-blocking channel sends when delivering signals. If the receiving end of the channel isn't ready and the channel is either unbuffered or full, the signal will be dropped. To avoid missing signals, the channel should be buffered and of the appropriate size. For a channel used for notification of just one signal value, a buffer of size 1 is sufficient.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1017": true}`.
Package documentation: [SA1017](https://staticcheck.dev/docs/checks/#SA1017)
## `SA1018`: strings.Replace called with n == 0, which does nothing
With n == 0, zero instances will be replaced. To replace all instances, use a negative number, or use strings.ReplaceAll.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1018": true}`.
Package documentation: [SA1018](https://staticcheck.dev/docs/checks/#SA1018)
## `SA1020`: Using an invalid host:port pair with a net.Listen-related function
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1020": true}`.
Package documentation: [SA1020](https://staticcheck.dev/docs/checks/#SA1020)
## `SA1021`: Using bytes.Equal to compare two net.IP
A net.IP stores an IPv4 or IPv6 address as a slice of bytes. The length of the slice for an IPv4 address, however, can be either 4 or 16 bytes long, using different ways of representing IPv4 addresses. In order to correctly compare two net.IPs, the net.IP.Equal method should be used, as it takes both representations into account.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1021": true}`.
Package documentation: [SA1021](https://staticcheck.dev/docs/checks/#SA1021)
## `SA1023`: Modifying the buffer in an io.Writer implementation
Write must not modify the slice data, even temporarily.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1023": true}`.
Package documentation: [SA1023](https://staticcheck.dev/docs/checks/#SA1023)
## `SA1024`: A string cutset contains duplicate characters
The strings.TrimLeft and strings.TrimRight functions take cutsets, not prefixes. A cutset is treated as a set of characters to remove from a string. For example,
strings.TrimLeft("42133word", "1234")
will result in the string "word" – any characters that are 1, 2, 3 or 4 are cut from the left of the string.
In order to remove one string from another, use strings.TrimPrefix instead.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA1024": true}`.
Package documentation: [SA1024](https://staticcheck.dev/docs/checks/#SA1024)
## `SA1025`: It is not possible to use (*time.Timer).Reset's return value correctly
Available since
2019.1
Default: off. Enable by setting `"analyses": {"SA1025": true}`.
Package documentation: [SA1025](https://staticcheck.dev/docs/checks/#SA1025)
## `SA1026`: Cannot marshal channels or functions
Available since
2019.2
Default: off. Enable by setting `"analyses": {"SA1026": true}`.
Package documentation: [SA1026](https://staticcheck.dev/docs/checks/#SA1026)
## `SA1027`: Atomic access to 64-bit variable must be 64-bit aligned
On ARM, x86-32, and 32-bit MIPS, it is the caller's responsibility to arrange for 64-bit alignment of 64-bit words accessed atomically. The first word in a variable or in an allocated struct, array, or slice can be relied upon to be 64-bit aligned.
You can use the structlayout tool to inspect the alignment of fields in a struct.
Available since
2019.2
Default: off. Enable by setting `"analyses": {"SA1027": true}`.
Package documentation: [SA1027](https://staticcheck.dev/docs/checks/#SA1027)
## `SA1028`: sort.Slice can only be used on slices
The first argument of sort.Slice must be a slice.
Available since
2020.1
Default: off. Enable by setting `"analyses": {"SA1028": true}`.
Package documentation: [SA1028](https://staticcheck.dev/docs/checks/#SA1028)
## `SA1029`: Inappropriate key in call to context.WithValue
The provided key must be comparable and should not be of type string or any other built-in type to avoid collisions between packages using context. Users of WithValue should define their own types for keys.
To avoid allocating when assigning to an interface{}, context keys often have concrete type struct{}. Alternatively, exported context key variables' static type should be a pointer or interface.
Available since
2020.1
Default: off. Enable by setting `"analyses": {"SA1029": true}`.
Package documentation: [SA1029](https://staticcheck.dev/docs/checks/#SA1029)
## `SA1030`: Invalid argument in call to a strconv function
This check validates the format, number base and bit size arguments of the various parsing and formatting functions in strconv.
Available since
2021.1
Default: off. Enable by setting `"analyses": {"SA1030": true}`.
Package documentation: [SA1030](https://staticcheck.dev/docs/checks/#SA1030)
## `SA1031`: Overlapping byte slices passed to an encoder
In an encoding function of the form Encode(dst, src), dst and src were found to reference the same memory. This can result in src bytes being overwritten before they are read, when the encoder writes more than one byte per src byte.
Available since
2024.1
Default: off. Enable by setting `"analyses": {"SA1031": true}`.
Package documentation: [SA1031](https://staticcheck.dev/docs/checks/#SA1031)
## `SA1032`: Wrong order of arguments to errors.Is
The first argument of the function errors.Is is the error that we have and the second argument is the error we're trying to match against. For example:
if errors.Is(err, io.EOF) { ... }
This check detects some cases where the two arguments have been swapped. It flags any calls where the first argument is referring to a package-level error variable, such as
if errors.Is(io.EOF, err) { /* this is wrong */ }
Available since
2024.1
Default: off. Enable by setting `"analyses": {"SA1032": true}`.
Package documentation: [SA1032](https://staticcheck.dev/docs/checks/#SA1032)
## `SA2001`: Empty critical section, did you mean to defer the unlock?
Empty critical sections of the kind
mu.Lock()
mu.Unlock()
are very often a typo, and the following was intended instead:
mu.Lock()
defer mu.Unlock()
Do note that sometimes empty critical sections can be useful, as a form of signaling to wait on another goroutine. Many times, there are simpler ways of achieving the same effect. When that isn't the case, the code should be amply commented to avoid confusion. Combining such comments with a //lint:ignore directive can be used to suppress this rare false positive.
Available since
2017.1
Default: on.
Package documentation: [SA2001](https://staticcheck.dev/docs/checks/#SA2001)
## `SA2002`: Called testing.T.FailNow or SkipNow in a goroutine, which isn't allowed
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA2002": true}`.
Package documentation: [SA2002](https://staticcheck.dev/docs/checks/#SA2002)
## `SA2003`: Deferred Lock right after locking, likely meant to defer Unlock instead
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA2003": true}`.
Package documentation: [SA2003](https://staticcheck.dev/docs/checks/#SA2003)
## `SA3000`: TestMain doesn't call os.Exit, hiding test failures
Test executables (and in turn 'go test') exit with a non-zero status code if any tests failed. When specifying your own TestMain function, it is your responsibility to arrange for this, by calling os.Exit with the correct code. The correct code is returned by (\*testing.M).Run, so the usual way of implementing TestMain is to end it with os.Exit(m.Run()).
Available since
2017.1
Default: on.
Package documentation: [SA3000](https://staticcheck.dev/docs/checks/#SA3000)
## `SA3001`: Assigning to b.N in benchmarks distorts the results
The testing package dynamically sets b.N to improve the reliability of benchmarks and uses it in computations to determine the duration of a single operation. Benchmark code must not alter b.N as this would falsify results.
Available since
2017.1
Default: on.
Package documentation: [SA3001](https://staticcheck.dev/docs/checks/#SA3001)
## `SA4000`: Binary operator has identical expressions on both sides
Available since
2017.1
Default: on.
Package documentation: [SA4000](https://staticcheck.dev/docs/checks/#SA4000)
## `SA4001`: &*x gets simplified to x, it does not copy x
Available since
2017.1
Default: on.
Package documentation: [SA4001](https://staticcheck.dev/docs/checks/#SA4001)
## `SA4003`: Comparing unsigned values against negative values is pointless
Available since
2017.1
Default: on.
Package documentation: [SA4003](https://staticcheck.dev/docs/checks/#SA4003)
## `SA4004`: The loop exits unconditionally after one iteration
Available since
2017.1
Default: on.
Package documentation: [SA4004](https://staticcheck.dev/docs/checks/#SA4004)
## `SA4005`: Field assignment that will never be observed. Did you mean to use a pointer receiver?
Available since
2021.1
Default: off. Enable by setting `"analyses": {"SA4005": true}`.
Package documentation: [SA4005](https://staticcheck.dev/docs/checks/#SA4005)
## `SA4006`: A value assigned to a variable is never read before being overwritten. Forgotten error check or dead code?
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA4006": true}`.
Package documentation: [SA4006](https://staticcheck.dev/docs/checks/#SA4006)
## `SA4008`: The variable in the loop condition never changes, are you incrementing the wrong variable?
For example:
for i := 0; i < 10; j++ { ... }
This may also occur when a loop can only execute once because of unconditional control flow that terminates the loop. For example, when a loop body contains an unconditional break, return, or panic:
func f() {
panic("oops")
}
func g() {
for i := 0; i < 10; i++ {
// f unconditionally calls panic, which means "i" is
// never incremented.
f()
}
}
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA4008": true}`.
Package documentation: [SA4008](https://staticcheck.dev/docs/checks/#SA4008)
## `SA4009`: A function argument is overwritten before its first use
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA4009": true}`.
Package documentation: [SA4009](https://staticcheck.dev/docs/checks/#SA4009)
## `SA4010`: The result of append will never be observed anywhere
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA4010": true}`.
Package documentation: [SA4010](https://staticcheck.dev/docs/checks/#SA4010)
## `SA4011`: Break statement with no effect. Did you mean to break out of an outer loop?
Available since
2017.1
Default: on.
Package documentation: [SA4011](https://staticcheck.dev/docs/checks/#SA4011)
## `SA4012`: Comparing a value against NaN even though no value is equal to NaN
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA4012": true}`.
Package documentation: [SA4012](https://staticcheck.dev/docs/checks/#SA4012)
## `SA4013`: Negating a boolean twice (!!b) is the same as writing b. This is either redundant, or a typo.
Available since
2017.1
Default: on.
Package documentation: [SA4013](https://staticcheck.dev/docs/checks/#SA4013)
## `SA4014`: An if/else if chain has repeated conditions and no side-effects; if the condition didn't match the first time, it won't match the second time, either
Available since
2017.1
Default: on.
Package documentation: [SA4014](https://staticcheck.dev/docs/checks/#SA4014)
## `SA4015`: Calling functions like math.Ceil on floats converted from integers doesn't do anything useful
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA4015": true}`.
Package documentation: [SA4015](https://staticcheck.dev/docs/checks/#SA4015)
## `SA4016`: Certain bitwise operations, such as x ^ 0, do not do anything useful
Available since
2017.1
Default: on.
Package documentation: [SA4016](https://staticcheck.dev/docs/checks/#SA4016)
## `SA4017`: Discarding the return values of a function without side effects, making the call pointless
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA4017": true}`.
Package documentation: [SA4017](https://staticcheck.dev/docs/checks/#SA4017)
## `SA4018`: Self-assignment of variables
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA4018": true}`.
Package documentation: [SA4018](https://staticcheck.dev/docs/checks/#SA4018)
## `SA4019`: Multiple, identical build constraints in the same file
Available since
2017.1
Default: on.
Package documentation: [SA4019](https://staticcheck.dev/docs/checks/#SA4019)
## `SA4020`: Unreachable case clause in a type switch
In a type switch like the following
type T struct{}
func (T) Read(b []byte) (int, error) { return 0, nil }
var v any = T{}
switch v.(type) {
case io.Reader:
// ...
case T:
// unreachable
}
the second case clause can never be reached because T implements io.Reader and case clauses are evaluated in source order.
Another example:
type T struct{}
func (T) Read(b []byte) (int, error) { return 0, nil }
func (T) Close() error { return nil }
var v any = T{}
switch v.(type) {
case io.Reader:
// ...
case io.ReadCloser:
// unreachable
}
Even though T has a Close method and thus implements io.ReadCloser, io.Reader will always match first. The method set of io.Reader is a subset of io.ReadCloser. Thus it is impossible to match the second case without matching the first case.
### Structurally equivalent interfaces {#hdr-Structurally_equivalent_interfaces}
A special case of the previous example are structurally identical interfaces. Given these declarations
type T error
type V error
func doSomething() error {
err, ok := doAnotherThing()
if ok {
return T(err)
}
return U(err)
}
the following type switch will have an unreachable case clause:
switch doSomething().(type) {
case T:
// ...
case V:
// unreachable
}
T will always match before V because they are structurally equivalent and therefore doSomething()'s return value implements both.
Available since
2019.2
Default: on.
Package documentation: [SA4020](https://staticcheck.dev/docs/checks/#SA4020)
## `SA4022`: Comparing the address of a variable against nil
Code such as 'if &x == nil' is meaningless, because taking the address of a variable always yields a non-nil pointer.
Available since
2020.1
Default: on.
Package documentation: [SA4022](https://staticcheck.dev/docs/checks/#SA4022)
## `SA4023`: Impossible comparison of interface value with untyped nil
Under the covers, interfaces are implemented as two elements, a type T and a value V. V is a concrete value such as an int, struct or pointer, never an interface itself, and has type T. For instance, if we store the int value 3 in an interface, the resulting interface value has, schematically, (T=int, V=3). The value V is also known as the interface's dynamic value, since a given interface variable might hold different values V (and corresponding types T) during the execution of the program.
An interface value is nil only if the V and T are both unset, (T=nil, V is not set), In particular, a nil interface will always hold a nil type. If we store a nil pointer of type \*int inside an interface value, the inner type will be \*int regardless of the value of the pointer: (T=\*int, V=nil). Such an interface value will therefore be non-nil even when the pointer value V inside is nil.
This situation can be confusing, and arises when a nil value is stored inside an interface value such as an error return:
func returnsError() error {
var p *MyError = nil
if bad() {
p = ErrBad
}
return p // Will always return a non-nil error.
}
If all goes well, the function returns a nil p, so the return value is an error interface value holding (T=\*MyError, V=nil). This means that if the caller compares the returned error to nil, it will always look as if there was an error even if nothing bad happened. To return a proper nil error to the caller, the function must return an explicit nil:
func returnsError() error {
if bad() {
return ErrBad
}
return nil
}
It's a good idea for functions that return errors always to use the error type in their signature (as we did above) rather than a concrete type such as \*MyError, to help guarantee the error is created correctly. As an example, os.Open returns an error even though, if not nil, it's always of concrete type \*os.PathError.
Similar situations to those described here can arise whenever interfaces are used. Just keep in mind that if any concrete value has been stored in the interface, the interface will not be nil. For more information, see The Laws of Reflection at [https://golang.org/doc/articles/laws\_of\_reflection.html](https://golang.org/doc/articles/laws_of_reflection.html).
This text has been copied from [https://golang.org/doc/faq#nil\_error](https://golang.org/doc/faq#nil_error), licensed under the Creative Commons Attribution 3.0 License.
Available since
2020.2
Default: off. Enable by setting `"analyses": {"SA4023": true}`.
Package documentation: [SA4023](https://staticcheck.dev/docs/checks/#SA4023)
## `SA4024`: Checking for impossible return value from a builtin function
Return values of the len and cap builtins cannot be negative.
See [https://golang.org/pkg/builtin/#len](https://golang.org/pkg/builtin/#len) and [https://golang.org/pkg/builtin/#cap](https://golang.org/pkg/builtin/#cap).
Example:
if len(slice) < 0 {
fmt.Println("unreachable code")
}
Available since
2021.1
Default: on.
Package documentation: [SA4024](https://staticcheck.dev/docs/checks/#SA4024)
## `SA4025`: Integer division of literals that results in zero
When dividing two integer constants, the result will also be an integer. Thus, a division such as 2 / 3 results in 0. This is true for all of the following examples:
_ = 2 / 3
const _ = 2 / 3
const _ float64 = 2 / 3
_ = float64(2 / 3)
Staticcheck will flag such divisions if both sides of the division are integer literals, as it is highly unlikely that the division was intended to truncate to zero. Staticcheck will not flag integer division involving named constants, to avoid noisy positives.
Available since
2021.1
Default: on.
Package documentation: [SA4025](https://staticcheck.dev/docs/checks/#SA4025)
## `SA4026`: Go constants cannot express negative zero
In IEEE 754 floating point math, zero has a sign and can be positive or negative. This can be useful in certain numerical code.
Go constants, however, cannot express negative zero. This means that the literals -0.0 and 0.0 have the same ideal value (zero) and will both represent positive zero at runtime.
To explicitly and reliably create a negative zero, you can use the math.Copysign function: math.Copysign(0, -1).
Available since
2021.1
Default: on.
Package documentation: [SA4026](https://staticcheck.dev/docs/checks/#SA4026)
## `SA4027`: (*net/url.URL).Query returns a copy, modifying it doesn't change the URL
(\*net/url.URL).Query parses the current value of net/url.URL.RawQuery and returns it as a map of type net/url.Values. Subsequent changes to this map will not affect the URL unless the map gets encoded and assigned to the URL's RawQuery.
As a consequence, the following code pattern is an expensive no-op: u.Query().Add(key, value).
Available since
2021.1
Default: on.
Package documentation: [SA4027](https://staticcheck.dev/docs/checks/#SA4027)
## `SA4028`: x % 1 is always zero
Available since
2022.1
Default: on.
Package documentation: [SA4028](https://staticcheck.dev/docs/checks/#SA4028)
## `SA4029`: Ineffective attempt at sorting slice
sort.Float64Slice, sort.IntSlice, and sort.StringSlice are types, not functions. Doing x = sort.StringSlice(x) does nothing, especially not sort any values. The correct usage is sort.Sort(sort.StringSlice(x)) or sort.StringSlice(x).Sort(), but there are more convenient helpers, namely sort.Float64s, sort.Ints, and sort.Strings.
Available since
2022.1
Default: on.
Package documentation: [SA4029](https://staticcheck.dev/docs/checks/#SA4029)
## `SA4030`: Ineffective attempt at generating random number
Functions in the math/rand package that accept upper limits, such as Intn, generate random numbers in the half-open interval \[0,n). In other words, the generated numbers will be >= 0 and \< n – they don't include n. rand.Intn(1) therefore doesn't generate 0 or 1, it always generates 0.
Available since
2022.1
Default: on.
Package documentation: [SA4030](https://staticcheck.dev/docs/checks/#SA4030)
## `SA4031`: Checking never-nil value against nil
Available since
2022.1
Default: off. Enable by setting `"analyses": {"SA4031": true}`.
Package documentation: [SA4031](https://staticcheck.dev/docs/checks/#SA4031)
## `SA4032`: Comparing runtime.GOOS or runtime.GOARCH against impossible value
Available since
2024.1
Default: on.
Package documentation: [SA4032](https://staticcheck.dev/docs/checks/#SA4032)
## `SA5000`: Assignment to nil map
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA5000": true}`.
Package documentation: [SA5000](https://staticcheck.dev/docs/checks/#SA5000)
## `SA5001`: Deferring Close before checking for a possible error
Available since
2017.1
Default: on.
Package documentation: [SA5001](https://staticcheck.dev/docs/checks/#SA5001)
## `SA5002`: The empty for loop ('for {}') spins and can block the scheduler
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA5002": true}`.
Package documentation: [SA5002](https://staticcheck.dev/docs/checks/#SA5002)
## `SA5003`: Defers in infinite loops will never execute
Defers are scoped to the surrounding function, not the surrounding block. In a function that never returns, i.e. one containing an infinite loop, defers will never execute.
Available since
2017.1
Default: on.
Package documentation: [SA5003](https://staticcheck.dev/docs/checks/#SA5003)
## `SA5004`: 'for { select { ...' with an empty default branch spins
Available since
2017.1
Default: on.
Package documentation: [SA5004](https://staticcheck.dev/docs/checks/#SA5004)
## `SA5005`: The finalizer references the finalized object, preventing garbage collection
A finalizer is a function associated with an object that runs when the garbage collector is ready to collect said object, that is when the object is no longer referenced by anything.
If the finalizer references the object, however, it will always remain as the final reference to that object, preventing the garbage collector from collecting the object. The finalizer will never run, and the object will never be collected, leading to a memory leak. That is why the finalizer should instead use its first argument to operate on the object. That way, the number of references can temporarily go to zero before the object is being passed to the finalizer.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA5005": true}`.
Package documentation: [SA5005](https://staticcheck.dev/docs/checks/#SA5005)
## `SA5007`: Infinite recursive call
A function that calls itself recursively needs to have an exit condition. Otherwise it will recurse forever, until the system runs out of memory.
This issue can be caused by simple bugs such as forgetting to add an exit condition. It can also happen "on purpose". Some languages have tail call optimization which makes certain infinite recursive calls safe to use. Go, however, does not implement TCO, and as such a loop should be used instead.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA5007": true}`.
Package documentation: [SA5007](https://staticcheck.dev/docs/checks/#SA5007)
## `SA5008`: Invalid struct tag
Available since
2019.2
Default: on.
Package documentation: [SA5008](https://staticcheck.dev/docs/checks/#SA5008)
## `SA5010`: Impossible type assertion
Some type assertions can be statically proven to be impossible. This is the case when the method sets of both arguments of the type assertion conflict with each other, for example by containing the same method with different signatures.
The Go compiler already applies this check when asserting from an interface value to a concrete type. If the concrete type misses methods from the interface, or if function signatures don't match, then the type assertion can never succeed.
This check applies the same logic when asserting from one interface to another. If both interface types contain the same method but with different signatures, then the type assertion can never succeed, either.
Available since
2020.1
Default: off. Enable by setting `"analyses": {"SA5010": true}`.
Package documentation: [SA5010](https://staticcheck.dev/docs/checks/#SA5010)
## `SA5011`: Possible nil pointer dereference
A pointer is being dereferenced unconditionally, while also being checked against nil in another place. This suggests that the pointer may be nil and dereferencing it may panic. This is commonly a result of improperly ordered code or missing return statements. Consider the following examples:
func fn(x *int) {
fmt.Println(*x)
// This nil check is equally important for the previous dereference
if x != nil {
foo(*x)
}
}
func TestFoo(t *testing.T) {
x := compute()
if x == nil {
t.Errorf("nil pointer received")
}
// t.Errorf does not abort the test, so if x is nil, the next line will panic.
foo(*x)
}
Staticcheck tries to deduce which functions abort control flow. For example, it is aware that a function will not continue execution after a call to panic or log.Fatal. However, sometimes this detection fails, in particular in the presence of conditionals. Consider the following example:
func Log(msg string, level int) {
fmt.Println(msg)
if level == levelFatal {
os.Exit(1)
}
}
func Fatal(msg string) {
Log(msg, levelFatal)
}
func fn(x *int) {
if x == nil {
Fatal("unexpected nil pointer")
}
fmt.Println(*x)
}
Staticcheck will flag the dereference of x, even though it is perfectly safe. Staticcheck is not able to deduce that a call to Fatal will exit the program. For the time being, the easiest workaround is to modify the definition of Fatal like so:
func Fatal(msg string) {
Log(msg, levelFatal)
panic("unreachable")
}
We also hard-code functions from common logging packages such as logrus. Please file an issue if we're missing support for a popular package.
Available since
2020.1
Default: off. Enable by setting `"analyses": {"SA5011": true}`.
Package documentation: [SA5011](https://staticcheck.dev/docs/checks/#SA5011)
## `SA5012`: Passing odd-sized slice to function expecting even size
Some functions that take slices as parameters expect the slices to have an even number of elements. Often, these functions treat elements in a slice as pairs. For example, strings.NewReplacer takes pairs of old and new strings, and calling it with an odd number of elements would be an error.
Available since
2020.2
Default: off. Enable by setting `"analyses": {"SA5012": true}`.
Package documentation: [SA5012](https://staticcheck.dev/docs/checks/#SA5012)
## `SA6000`: Using regexp.Match or related in a loop, should use regexp.Compile
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA6000": true}`.
Package documentation: [SA6000](https://staticcheck.dev/docs/checks/#SA6000)
## `SA6001`: Missing an optimization opportunity when indexing maps by byte slices
Map keys must be comparable, which precludes the use of byte slices. This usually leads to using string keys and converting byte slices to strings.
Normally, a conversion of a byte slice to a string needs to copy the data and causes allocations. The compiler, however, recognizes m\[string(b)] and uses the data of b directly, without copying it, because it knows that the data can't change during the map lookup. This leads to the counter-intuitive situation that
k := string(b)
println(m[k])
println(m[k])
will be less efficient than
println(m[string(b)])
println(m[string(b)])
because the first version needs to copy and allocate, while the second one does not.
For some history on this optimization, check out commit f5f5a8b6209f84961687d993b93ea0d397f5d5bf in the Go repository.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA6001": true}`.
Package documentation: [SA6001](https://staticcheck.dev/docs/checks/#SA6001)
## `SA6002`: Storing non-pointer values in sync.Pool allocates memory
A sync.Pool is used to avoid unnecessary allocations and reduce the amount of work the garbage collector has to do.
When passing a value that is not a pointer to a function that accepts an interface, the value needs to be placed on the heap, which means an additional allocation. Slices are a common thing to put in sync.Pools, and they're structs with 3 fields (length, capacity, and a pointer to an array). In order to avoid the extra allocation, one should store a pointer to the slice instead.
See the comments on [https://go-review.googlesource.com/c/go/+/24371](https://go-review.googlesource.com/c/go/+/24371) that discuss this problem.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA6002": true}`.
Package documentation: [SA6002](https://staticcheck.dev/docs/checks/#SA6002)
## `SA6003`: Converting a string to a slice of runes before ranging over it
You may want to loop over the runes in a string. Instead of converting the string to a slice of runes and looping over that, you can loop over the string itself. That is,
for _, r := range s {}
and
for _, r := range []rune(s) {}
will yield the same values. The first version, however, will be faster and avoid unnecessary memory allocations.
Do note that if you are interested in the indices, ranging over a string and over a slice of runes will yield different indices. The first one yields byte offsets, while the second one yields indices in the slice of runes.
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA6003": true}`.
Package documentation: [SA6003](https://staticcheck.dev/docs/checks/#SA6003)
## `SA6005`: Inefficient string comparison with strings.ToLower or strings.ToUpper
Converting two strings to the same case and comparing them like so
if strings.ToLower(s1) == strings.ToLower(s2) {
...
}
is significantly more expensive than comparing them with strings.EqualFold(s1, s2). This is due to memory usage as well as computational complexity.
strings.ToLower will have to allocate memory for the new strings, as well as convert both strings fully, even if they differ on the very first byte. strings.EqualFold, on the other hand, compares the strings one character at a time. It doesn't need to create two intermediate strings and can return as soon as the first non-matching character has been found.
For a more in-depth explanation of this issue, see [https://blog.digitalocean.com/how-to-efficiently-compare-strings-in-go/](https://blog.digitalocean.com/how-to-efficiently-compare-strings-in-go/)
Available since
2019.2
Default: on.
Package documentation: [SA6005](https://staticcheck.dev/docs/checks/#SA6005)
## `SA6006`: Using io.WriteString to write []byte
Using io.WriteString to write a slice of bytes, as in
io.WriteString(w, string(b))
is both unnecessary and inefficient. Converting from \[]byte to string has to allocate and copy the data, and we could simply use w.Write(b) instead.
Available since
2024.1
Default: on.
Package documentation: [SA6006](https://staticcheck.dev/docs/checks/#SA6006)
## `SA9001`: Defers in range loops may not run when you expect them to
Available since
2017.1
Default: off. Enable by setting `"analyses": {"SA9001": true}`.
Package documentation: [SA9001](https://staticcheck.dev/docs/checks/#SA9001)
## `SA9002`: Using a non-octal os.FileMode that looks like it was meant to be in octal.
Available since
2017.1
Default: on.
Package documentation: [SA9002](https://staticcheck.dev/docs/checks/#SA9002)
## `SA9003`: Empty body in an if or else branch
Available since
2017.1, non-default
Default: off. Enable by setting `"analyses": {"SA9003": true}`.
Package documentation: [SA9003](https://staticcheck.dev/docs/checks/#SA9003)
## `SA9004`: Only the first constant has an explicit type
In a constant declaration such as the following:
const (
First byte = 1
Second = 2
)
the constant Second does not have the same type as the constant First. This construct shouldn't be confused with
const (
First byte = iota
Second
)
where First and Second do indeed have the same type. The type is only passed on when no explicit value is assigned to the constant.
When declaring enumerations with explicit values it is therefore important not to write
const (
EnumFirst EnumType = 1
EnumSecond = 2
EnumThird = 3
)
This discrepancy in types can cause various confusing behaviors and bugs.
### Wrong type in variable declarations {#hdr-Wrong_type_in_variable_declarations}
The most obvious issue with such incorrect enumerations expresses itself as a compile error:
package pkg
const (
EnumFirst uint8 = 1
EnumSecond = 2
)
func fn(useFirst bool) {
x := EnumSecond
if useFirst {
x = EnumFirst
}
}
fails to compile with
./const.go:11:5: cannot use EnumFirst (type uint8) as type int in assignment
### Losing method sets {#hdr-Losing_method_sets}
A more subtle issue occurs with types that have methods and optional interfaces. Consider the following:
package main
import "fmt"
type Enum int
func (e Enum) String() string {
return "an enum"
}
const (
EnumFirst Enum = 1
EnumSecond = 2
)
func main() {
fmt.Println(EnumFirst)
fmt.Println(EnumSecond)
}
This code will output
an enum
2
as EnumSecond has no explicit type, and thus defaults to int.
Available since
2019.1
Default: on.
Package documentation: [SA9004](https://staticcheck.dev/docs/checks/#SA9004)
## `SA9005`: Trying to marshal a struct with no public fields nor custom marshaling
The encoding/json and encoding/xml packages only operate on exported fields in structs, not unexported ones. It is usually an error to try to (un)marshal structs that only consist of unexported fields.
This check will not flag calls involving types that define custom marshaling behavior, e.g. via MarshalJSON methods. It will also not flag empty structs.
Available since
2019.2
Default: off. Enable by setting `"analyses": {"SA9005": true}`.
Package documentation: [SA9005](https://staticcheck.dev/docs/checks/#SA9005)
## `SA9006`: Dubious bit shifting of a fixed size integer value
Bit shifting a value past its size will always clear the value.
For instance:
v := int8(42)
v >>= 8
will always result in 0.
This check flags bit shifting operations on fixed size integer values only. That is, int, uint and uintptr are never flagged to avoid potential false positives in somewhat exotic but valid bit twiddling tricks:
// Clear any value above 32 bits if integers are more than 32 bits.
func f(i int) int {
v := i >> 32
v = v << 32
return i-v
}
Available since
2020.2
Default: on.
Package documentation: [SA9006](https://staticcheck.dev/docs/checks/#SA9006)
## `SA9007`: Deleting a directory that shouldn't be deleted
It is virtually never correct to delete system directories such as /tmp or the user's home directory. However, it can be fairly easy to do by mistake, for example by mistakenly using os.TempDir instead of ioutil.TempDir, or by forgetting to add a suffix to the result of os.UserHomeDir.
Writing
d := os.TempDir()
defer os.RemoveAll(d)
in your unit tests will have a devastating effect on the stability of your system.
This check flags attempts at deleting the following directories:
\- os.TempDir - os.UserCacheDir - os.UserConfigDir - os.UserHomeDir
Available since
2022.1
Default: off. Enable by setting `"analyses": {"SA9007": true}`.
Package documentation: [SA9007](https://staticcheck.dev/docs/checks/#SA9007)
## `SA9008`: else branch of a type assertion is probably not reading the right value
When declaring variables as part of an if statement (like in 'if foo := ...; foo {'), the same variables will also be in the scope of the else branch. This means that in the following example
if x, ok := x.(int); ok {
// ...
} else {
fmt.Printf("unexpected type %T", x)
}
x in the else branch will refer to the x from x, ok :=; it will not refer to the x that is being type-asserted. The result of a failed type assertion is the zero value of the type that is being asserted to, so x in the else branch will always have the value 0 and the type int.
Available since
2022.1
Default: off. Enable by setting `"analyses": {"SA9008": true}`.
Package documentation: [SA9008](https://staticcheck.dev/docs/checks/#SA9008)
## `SA9009`: Ineffectual Go compiler directive
A potential Go compiler directive was found, but is ineffectual as it begins with whitespace.
Available since
2024.1
Default: on.
Package documentation: [SA9009](https://staticcheck.dev/docs/checks/#SA9009)
## `ST1000`: Incorrect or missing package comment
Packages must have a package comment that is formatted according to the guidelines laid out in [https://go.dev/wiki/CodeReviewComments#package-comments](https://go.dev/wiki/CodeReviewComments#package-comments).
Available since
2019.1, non-default
Default: off. Enable by setting `"analyses": {"ST1000": true}`.
Package documentation: [ST1000](https://staticcheck.dev/docs/checks/#ST1000)
## `ST1001`: Dot imports are discouraged
Dot imports that aren't in external test packages are discouraged.
The dot\_import\_whitelist option can be used to whitelist certain imports.
Quoting Go Code Review Comments:
> The import . form can be useful in tests that, due to circular > dependencies, cannot be made part of the package being tested: > > package foo\_test > > import ( > "bar/testutil" // also imports "foo" > . "foo" > ) > > In this case, the test file cannot be in package foo because it > uses bar/testutil, which imports foo. So we use the import . > form to let the file pretend to be part of package foo even though > it is not. Except for this one case, do not use import . in your > programs. It makes the programs much harder to read because it is > unclear whether a name like Quux is a top-level identifier in the > current package or in an imported package.
Available since
2019.1
Options
dot_import_whitelist
Default: off. Enable by setting `"analyses": {"ST1001": true}`.
Package documentation: [ST1001](https://staticcheck.dev/docs/checks/#ST1001)
## `ST1003`: Poorly chosen identifier
Identifiers, such as variable and package names, follow certain rules.
See the following links for details:
\- [https://go.dev/doc/effective\_go#package-names](https://go.dev/doc/effective_go#package-names) - [https://go.dev/doc/effective\_go#mixed-caps](https://go.dev/doc/effective_go#mixed-caps) - [https://go.dev/wiki/CodeReviewComments#initialisms](https://go.dev/wiki/CodeReviewComments#initialisms) - [https://go.dev/wiki/CodeReviewComments#variable-names](https://go.dev/wiki/CodeReviewComments#variable-names)
Available since
2019.1, non-default
Options
initialisms
Default: off. Enable by setting `"analyses": {"ST1003": true}`.
Package documentation: [ST1003](https://staticcheck.dev/docs/checks/#ST1003)
## `ST1005`: Incorrectly formatted error string
Error strings follow a set of guidelines to ensure uniformity and good composability.
Quoting Go Code Review Comments:
> Error strings should not be capitalized (unless beginning with > proper nouns or acronyms) or end with punctuation, since they are > usually printed following other context. That is, use > fmt.Errorf("something bad") not fmt.Errorf("Something bad"), so > that log.Printf("Reading %s: %v", filename, err) formats without a > spurious capital letter mid-message.
Available since
2019.1
Default: off. Enable by setting `"analyses": {"ST1005": true}`.
Package documentation: [ST1005](https://staticcheck.dev/docs/checks/#ST1005)
## `ST1006`: Poorly chosen receiver name
Quoting Go Code Review Comments:
> The name of a method's receiver should be a reflection of its > identity; often a one or two letter abbreviation of its type > suffices (such as "c" or "cl" for "Client"). Don't use generic > names such as "me", "this" or "self", identifiers typical of > object-oriented languages that place more emphasis on methods as > opposed to functions. The name need not be as descriptive as that > of a method argument, as its role is obvious and serves no > documentary purpose. It can be very short as it will appear on > almost every line of every method of the type; familiarity admits > brevity. Be consistent, too: if you call the receiver "c" in one > method, don't call it "cl" in another.
Available since
2019.1
Default: off. Enable by setting `"analyses": {"ST1006": true}`.
Package documentation: [ST1006](https://staticcheck.dev/docs/checks/#ST1006)
## `ST1008`: A function's error value should be its last return value
A function's error value should be its last return value.
Available since
2019.1
Default: off. Enable by setting `"analyses": {"ST1008": true}`.
Package documentation: [ST1008](https://staticcheck.dev/docs/checks/#ST1008)
## `ST1011`: Poorly chosen name for variable of type time.Duration
time.Duration values represent an amount of time, which is represented as a count of nanoseconds. An expression like 5 \* time.Microsecond yields the value 5000. It is therefore not appropriate to suffix a variable of type time.Duration with any time unit, such as Msec or Milli.
Available since
2019.1
Default: off. Enable by setting `"analyses": {"ST1011": true}`.
Package documentation: [ST1011](https://staticcheck.dev/docs/checks/#ST1011)
## `ST1012`: Poorly chosen name for error variable
Error variables that are part of an API should be called errFoo or ErrFoo.
Available since
2019.1
Default: off. Enable by setting `"analyses": {"ST1012": true}`.
Package documentation: [ST1012](https://staticcheck.dev/docs/checks/#ST1012)
## `ST1013`: Should use constants for HTTP error codes, not magic numbers
HTTP has a tremendous number of status codes. While some of those are well known (200, 400, 404, 500), most of them are not. The net/http package provides constants for all status codes that are part of the various specifications. It is recommended to use these constants instead of hard-coding magic numbers, to vastly improve the readability of your code.
Available since
2019.1
Options
http_status_code_whitelist
Default: off. Enable by setting `"analyses": {"ST1013": true}`.
Package documentation: [ST1013](https://staticcheck.dev/docs/checks/#ST1013)
## `ST1015`: A switch's default case should be the first or last case
Available since
2019.1
Default: off. Enable by setting `"analyses": {"ST1015": true}`.
Package documentation: [ST1015](https://staticcheck.dev/docs/checks/#ST1015)
## `ST1016`: Use consistent method receiver names
Available since
2019.1, non-default
Default: off. Enable by setting `"analyses": {"ST1016": true}`.
Package documentation: [ST1016](https://staticcheck.dev/docs/checks/#ST1016)
## `ST1017`: Don't use Yoda conditions
Yoda conditions are conditions of the kind 'if 42 == x', where the literal is on the left side of the comparison. These are a common idiom in languages in which assignment is an expression, to avoid bugs of the kind 'if (x = 42)'. In Go, which doesn't allow for this kind of bug, we prefer the more idiomatic 'if x == 42'.
Available since
2019.2
Default: off. Enable by setting `"analyses": {"ST1017": true}`.
Package documentation: [ST1017](https://staticcheck.dev/docs/checks/#ST1017)
## `ST1018`: Avoid zero-width and control characters in string literals
Available since
2019.2
Default: off. Enable by setting `"analyses": {"ST1018": true}`.
Package documentation: [ST1018](https://staticcheck.dev/docs/checks/#ST1018)
## `ST1019`: Importing the same package multiple times
Go allows importing the same package multiple times, as long as different import aliases are being used. That is, the following bit of code is valid:
import (
"fmt"
fumpt "fmt"
format "fmt"
_ "fmt"
)
However, this is very rarely done on purpose. Usually, it is a sign of code that got refactored, accidentally adding duplicate import statements. It is also a rarely known feature, which may contribute to confusion.
Do note that sometimes, this feature may be used intentionally (see for example [https://github.com/golang/go/commit/3409ce39bfd7584523b7a8c150a310cea92d879d](https://github.com/golang/go/commit/3409ce39bfd7584523b7a8c150a310cea92d879d)) – if you want to allow this pattern in your code base, you're advised to disable this check.
Available since
2020.1
Default: off. Enable by setting `"analyses": {"ST1019": true}`.
Package documentation: [ST1019](https://staticcheck.dev/docs/checks/#ST1019)
## `ST1020`: The documentation of an exported function should start with the function's name
Doc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.
If every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.
See [https://go.dev/doc/effective\_go#commentary](https://go.dev/doc/effective_go#commentary) for more information on how to write good documentation.
Available since
2020.1, non-default
Default: off. Enable by setting `"analyses": {"ST1020": true}`.
Package documentation: [ST1020](https://staticcheck.dev/docs/checks/#ST1020)
## `ST1021`: The documentation of an exported type should start with type's name
Doc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.
If every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.
See [https://go.dev/doc/effective\_go#commentary](https://go.dev/doc/effective_go#commentary) for more information on how to write good documentation.
Available since
2020.1, non-default
Default: off. Enable by setting `"analyses": {"ST1021": true}`.
Package documentation: [ST1021](https://staticcheck.dev/docs/checks/#ST1021)
## `ST1022`: The documentation of an exported variable or constant should start with variable's name
Doc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared.
If every doc comment begins with the name of the item it describes, you can use the doc subcommand of the go tool and run the output through grep.
See [https://go.dev/doc/effective\_go#commentary](https://go.dev/doc/effective_go#commentary) for more information on how to write good documentation.
Available since
2020.1, non-default
Default: off. Enable by setting `"analyses": {"ST1022": true}`.
Package documentation: [ST1022](https://staticcheck.dev/docs/checks/#ST1022)
## `ST1023`: Redundant type in variable declaration
Available since
2021.1, non-default
Default: off. Enable by setting `"analyses": {"ST1023": true}`.
Package documentation: [ST1023](https://staticcheck.dev/docs/checks/#)
## `any`: replace interface{} with any
The any analyzer suggests replacing uses of the empty interface type, \`interface{}\`, with the \`any\` alias, which was introduced in Go 1.18. This is a purely stylistic change that makes code more readable.
Default: on.
Package documentation: [any](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#any)
## `appendclipped`: simplify append chains using slices.Concat
The appendclipped analyzer suggests replacing chains of append calls with a single call to slices.Concat, which was added in Go 1.21. For example, append(append(s, s1...), s2...) would be simplified to slices.Concat(s, s1, s2).
In the simple case of appending to a newly allocated slice, such as append(\[]T(nil), s...), the analyzer suggests the more concise slices.Clone(s). For byte slices, it will prefer bytes.Clone if the "bytes" package is already imported.
This fix is only applied when the base of the append tower is a "clipped" slice, meaning its length and capacity are equal (e.g. x\[:0:0] or \[]T{}). This is to avoid changing program behavior by eliminating intended side effects on the base slice's underlying array.
This analyzer is currently disabled by default as the transformation does not preserve the nilness of the base slice in all cases; see [https://go.dev/issue/73557](https://go.dev/issue/73557).
Default: off. Enable by setting `"analyses": {"appendclipped": true}`.
Package documentation: [appendclipped](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#appendclipped)
## `appends`: check for missing values after append
This checker reports calls to append that pass no values to be appended to the slice.
s := []string{"a", "b", "c"}
_ = append(s)
Such calls are always no-ops and often indicate an underlying mistake.
Default: on.
Package documentation: [appends](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/appends)
## `asmdecl`: report mismatches between assembly files and Go declarations
Default: on.
Package documentation: [asmdecl](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/asmdecl)
## `assign`: check for useless assignments
This checker reports assignments of the form x = x or a\[i] = a\[i]. These are almost always useless, and even when they aren't they are usually a mistake.
Default: on.
Package documentation: [assign](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/assign)
## `atomic`: check for common mistakes using the sync/atomic package
The atomic checker looks for assignment statements of the form:
x = atomic.AddUint64(&x, 1)
which are not atomic.
Default: on.
Package documentation: [atomic](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/atomic)
## `atomicalign`: check for non-64-bits-aligned arguments to sync/atomic functions
Default: on.
Package documentation: [atomicalign](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/atomicalign)
## `bloop`: replace for-range over b.N with b.Loop
The bloop analyzer suggests replacing benchmark loops of the form \`for i := 0; i \< b.N; i++\` or \`for range b.N\` with the more modern \`for b.Loop()\`, which was added in Go 1.24.
This change makes benchmark code more readable and also removes the need for manual timer control, so any preceding calls to b.StartTimer, b.StopTimer, or b.ResetTimer within the same function will also be removed.
Caveats: The b.Loop() method is designed to prevent the compiler from optimizing away the benchmark loop, which can occasionally result in slower execution due to increased allocations in some specific cases. Since its fix may change the performance of nanosecond-scale benchmarks, bloop is disabled by default in the \`go fix\` analyzer suite; see golang/go#74967.
Default: on.
Package documentation: [bloop](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#bloop)
## `bools`: check for common mistakes involving boolean operators
Default: on.
Package documentation: [bools](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/bools)
## `buildtag`: check //go:build and // +build directives
Default: on.
Package documentation: [buildtag](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/buildtag)
## `cgocall`: detect some violations of the cgo pointer passing rules
Check for invalid cgo pointer passing. This looks for code that uses cgo to call C code passing values whose types are almost always invalid according to the cgo pointer sharing rules. Specifically, it warns about attempts to pass a Go chan, map, func, or slice to C, either directly, or via a pointer, array, or struct.
Default: on.
Package documentation: [cgocall](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/cgocall)
## `composites`: check for unkeyed composite literals
This analyzer reports a diagnostic for composite literals of struct types imported from another package that do not use the field-keyed syntax. Such literals are fragile because the addition of a new field (even if unexported) to the struct will cause compilation to fail.
As an example,
err = &net.DNSConfigError{err}
should be replaced by:
err = &net.DNSConfigError{Err: err}
Default: on.
Package documentation: [composites](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/composite)
## `copylocks`: check for locks erroneously passed by value
Inadvertently copying a value containing a lock, such as sync.Mutex or sync.WaitGroup, may cause both copies to malfunction. Generally such values should be referred to through a pointer.
Default: on.
Package documentation: [copylocks](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/copylock)
## `deepequalerrors`: check for calls of reflect.DeepEqual on error values
The deepequalerrors checker looks for calls of the form:
reflect.DeepEqual(err1, err2)
where err1 and err2 are errors. Using reflect.DeepEqual to compare errors is discouraged.
Default: on.
Package documentation: [deepequalerrors](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/deepequalerrors)
## `defers`: report common mistakes in defer statements
The defers analyzer reports a diagnostic when a defer statement would result in a non-deferred call to time.Since, as experience has shown that this is nearly always a mistake.
For example:
start := time.Now()
...
defer recordLatency(time.Since(start)) // error: call to time.Since is not deferred
The correct code is:
defer func() { recordLatency(time.Since(start)) }()
Default: on.
Package documentation: [defers](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/defers)
## `deprecated`: check for use of deprecated identifiers
The deprecated analyzer looks for deprecated symbols and package imports.
See [https://go.dev/wiki/Deprecated](https://go.dev/wiki/Deprecated) to learn about Go's convention for documenting and signaling deprecated identifiers.
Default: on.
Package documentation: [deprecated](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/deprecated)
## `directive`: check Go toolchain directives such as //go:debug
This analyzer checks for problems with known Go toolchain directives in all Go source files in a package directory, even those excluded by //go:build constraints, and all non-Go source files too.
For //go:debug (see [https://go.dev/doc/godebug](https://go.dev/doc/godebug)), the analyzer checks that the directives are placed only in Go source files, only above the package comment, and only in package main or \*\_test.go files.
Support for other known directives may be added in the future.
This analyzer does not check //go:build, which is handled by the buildtag analyzer.
Default: on.
Package documentation: [directive](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/directive)
## `embed`: check //go:embed directive usage
This analyzer checks that the embed package is imported if //go:embed directives are present, providing a suggested fix to add the import if it is missing.
This analyzer also checks that //go:embed directives precede the declaration of a single variable.
Default: on.
Package documentation: [embed](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/embeddirective)
## `errorsas`: report passing non-pointer or non-error values to errors.As
The errorsas analyzer reports calls to errors.As where the type of the second argument is not a pointer to a type implementing error.
Default: on.
Package documentation: [errorsas](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/errorsas)
## `errorsastype`: replace errors.As with errors.AsType[T]
This analyzer suggests fixes to simplify uses of [errors.As](/errors#As) of this form:
var myerr *MyErr
if errors.As(err, &myerr) {
handle(myerr)
}
by using the less error-prone generic [errors.AsType](/errors#AsType) function, introduced in Go 1.26:
if myerr, ok := errors.AsType[*MyErr](err); ok {
handle(myerr)
}
The fix is only offered if the var declaration has the form shown and there are no uses of myerr outside the if statement.
Default: on.
Package documentation: [errorsastype](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#errorsastype)
## `fillreturns`: suggest fixes for errors due to an incorrect number of return values
This checker provides suggested fixes for type errors of the type "wrong number of return values (want %d, got %d)". For example:
func m() (int, string, *bool, error) {
return
}
will turn into
func m() (int, string, *bool, error) {
return 0, "", nil, nil
}
This functionality is similar to [https://github.com/sqs/goreturns](https://github.com/sqs/goreturns).
Default: on.
Package documentation: [fillreturns](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/fillreturns)
## `fmtappendf`: replace []byte(fmt.Sprintf) with fmt.Appendf
The fmtappendf analyzer suggests replacing \`\[]byte(fmt.Sprintf(...))\` with \`fmt.Appendf(nil, ...)\`. This avoids the intermediate allocation of a string by Sprintf, making the code more efficient. The suggestion also applies to fmt.Sprint and fmt.Sprintln.
Default: on.
Package documentation: [fmtappendf](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#fmtappendf)
## `forvar`: remove redundant re-declaration of loop variables
The forvar analyzer removes unnecessary shadowing of loop variables. Before Go 1.22, it was common to write \`for \_, x := range s { x := x ... }\` to create a fresh variable for each iteration. Go 1.22 changed the semantics of \`for\` loops, making this pattern redundant. This analyzer removes the unnecessary \`x := x\` statement.
This fix only applies to \`range\` loops.
Default: on.
Package documentation: [forvar](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#forvar)
## `framepointer`: report assembly that clobbers the frame pointer before saving it
Default: on.
Package documentation: [framepointer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/framepointer)
## `hostport`: check format of addresses passed to net.Dial
This analyzer flags code that produce network address strings using fmt.Sprintf, as in this example:
addr := fmt.Sprintf("%s:%d", host, 12345) // "will not work with IPv6"
...
conn, err := net.Dial("tcp", addr) // "when passed to dial here"
The analyzer suggests a fix to use the correct approach, a call to net.JoinHostPort:
addr := net.JoinHostPort(host, "12345")
...
conn, err := net.Dial("tcp", addr)
A similar diagnostic and fix are produced for a format string of "%s:%s".
Default: on.
Package documentation: [hostport](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/hostport)
## `httpresponse`: check for mistakes using HTTP responses
A common mistake when using the net/http package is to defer a function call to close the http.Response Body before checking the error that determines whether the response is valid:
resp, err := http.Head(url)
defer resp.Body.Close()
if err != nil {
log.Fatal(err)
}
// (defer statement belongs here)
This checker helps uncover latent nil dereference bugs by reporting a diagnostic for such mistakes.
Default: on.
Package documentation: [httpresponse](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/httpresponse)
## `ifaceassert`: detect impossible interface-to-interface type assertions
This checker flags type assertions v.(T) and corresponding type-switch cases in which the static type V of v is an interface that cannot possibly implement the target interface T. This occurs when V and T contain methods with the same name but different signatures. Example:
var v interface {
Read()
}
_ = v.(io.Reader)
The Read method in v has a different signature than the Read method in io.Reader, so this assertion cannot succeed.
Default: on.
Package documentation: [ifaceassert](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/ifaceassert)
## `infertypeargs`: check for unnecessary type arguments in call expressions
Explicit type arguments may be omitted from call expressions if they can be inferred from function arguments, or from other type arguments:
func f[T any](T) {}
func _() {
f[string]("foo") // string could be inferred
}
Default: on.
Package documentation: [infertypeargs](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/infertypeargs)
## `inline`: apply fixes based on 'go:fix inline' comment directives
The inline analyzer inlines functions and constants that are marked for inlining.
\## Functions
Given a function that is marked for inlining, like this one:
//go:fix inline
func Square(x int) int { return Pow(x, 2) }
this analyzer will recommend that calls to the function elsewhere, in the same or other packages, should be inlined.
Inlining can be used to move off of a deprecated function:
// Deprecated: prefer Pow(x, 2).
//go:fix inline
func Square(x int) int { return Pow(x, 2) }
It can also be used to move off of an obsolete package, as when the import path has changed or a higher major version is available:
package pkg
import pkg2 "pkg/v2"
//go:fix inline
func F() { pkg2.F(nil) }
Replacing a call pkg.F() by pkg2.F(nil) can have no effect on the program, so this mechanism provides a low-risk way to update large numbers of calls. We recommend, where possible, expressing the old API in terms of the new one to enable automatic migration.
The inliner takes care to avoid behavior changes, even subtle ones, such as changes to the order in which argument expressions are evaluated. When it cannot safely eliminate all parameter variables, it may introduce a "binding declaration" of the form
var params = args
to evaluate argument expressions in the correct order and bind them to parameter variables. Since the resulting code transformation may be stylistically suboptimal, such inlinings may be disabled by specifying the -inline.allow\_binding\_decl=false flag to the analyzer driver.
(In cases where it is not safe to "reduce" a call—that is, to replace a call f(x) by the body of function f, suitably substituted—the inliner machinery is capable of replacing f by a function literal, func(){...}(). However, the inline analyzer discards all such "literalizations" unconditionally, again on grounds of style.)
\## Constants
Given a constant that is marked for inlining, like this one:
//go:fix inline
const Ptr = Pointer
this analyzer will recommend that uses of Ptr should be replaced with Pointer.
As with functions, inlining can be used to replace deprecated constants and constants in obsolete packages.
A constant definition can be marked for inlining only if it refers to another named constant.
The "//go:fix inline" comment must appear before a single const declaration on its own, as above; before a const declaration that is part of a group, as in this case:
const (
C = 1
//go:fix inline
Ptr = Pointer
)
or before a group, applying to every constant in the group:
//go:fix inline
const (
Ptr = Pointer
Val = Value
)
The proposal [https://go.dev/issue/32816](https://go.dev/issue/32816) introduces the "//go:fix inline" directives.
You can use this command to apply inline fixes en masse:
$ go run golang.org/x/tools/go/analysis/passes/inline/cmd/inline@latest -fix ./...
Default: on.
Package documentation: [inline](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/inline)
## `loopclosure`: check references to loop variables from within nested functions
This analyzer reports places where a function literal references the iteration variable of an enclosing loop, and the loop calls the function in such a way (e.g. with go or defer) that it may outlive the loop iteration and possibly observe the wrong value of the variable.
Note: An iteration variable can only outlive a loop iteration in Go versions \<=1.21. In Go 1.22 and later, the loop variable lifetimes changed to create a new iteration variable per loop iteration. (See go.dev/issue/60078.)
In this example, all the deferred functions run after the loop has completed, so all observe the final value of v \[\
## `lostcancel`: check cancel func returned by context.WithCancel is called
The cancellation function returned by context.WithCancel, WithTimeout, WithDeadline and variants such as WithCancelCause must be called, or the new context will remain live until its parent context is cancelled. (The background context is never cancelled.)
Default: on.
Package documentation: [lostcancel](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/lostcancel)
## `maprange`: checks for unnecessary calls to maps.Keys and maps.Values in range statements
Consider a loop written like this:
for val := range maps.Values(m) {
fmt.Println(val)
}
This should instead be written without the call to maps.Values:
for _, val := range m {
fmt.Println(val)
}
golang.org/x/exp/maps returns slices for Keys/Values instead of iterators, but unnecessary calls should similarly be removed:
for _, key := range maps.Keys(m) {
fmt.Println(key)
}
should be rewritten as:
for key := range m {
fmt.Println(key)
}
Default: on.
Package documentation: [maprange](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/maprange)
## `mapsloop`: replace explicit loops over maps with calls to maps package
The mapsloop analyzer replaces loops of the form
for k, v := range x { m[k] = v }
with a single call to a function from the \`maps\` package, added in Go 1.23. Depending on the context, this could be \`maps.Copy\`, \`maps.Insert\`, \`maps.Clone\`, or \`maps.Collect\`.
The transformation to \`maps.Clone\` is applied conservatively, as it preserves the nilness of the source map, which may be a subtle change in behavior if the original code did not handle a nil map in the same way.
Default: on.
Package documentation: [mapsloop](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#mapsloop)
## `minmax`: replace if/else statements with calls to min or max
The minmax analyzer simplifies conditional assignments by suggesting the use of the built-in \`min\` and \`max\` functions, introduced in Go 1.21. For example,
if a < b { x = a } else { x = b }
is replaced by
x = min(a, b).
This analyzer avoids making suggestions for floating-point types, as the behavior of \`min\` and \`max\` with NaN values can differ from the original if/else statement.
Default: on.
Package documentation: [minmax](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#minmax)
## `newexpr`: simplify code by using go1.26's new(expr)
This analyzer finds declarations of functions of this form:
func varOf(x int) *int { return &x }
and suggests a fix to turn them into inlinable wrappers around go1.26's built-in new(expr) function:
//go:fix inline
func varOf(x int) *int { return new(x) }
(The directive comment causes the 'inline' analyzer to suggest that calls to such functions are inlined.)
In addition, this analyzer suggests a fix for each call to one of the functions before it is transformed, so that
use(varOf(123))
is replaced by:
use(new(123))
Wrapper functions such as varOf are common when working with Go serialization packages such as for JSON or protobuf, where pointers are often used to express optionality.
Default: on.
Package documentation: [newexpr](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#newexpr)
## `nilfunc`: check for useless comparisons between functions and nil
A useless comparison is one like f == nil as opposed to f() == nil.
Default: on.
Package documentation: [nilfunc](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/nilfunc)
## `nilness`: check for redundant or impossible nil comparisons
The nilness checker inspects the control-flow graph of each function in a package and reports nil pointer dereferences, degenerate nil pointers, and panics with nil values. A degenerate comparison is of the form x==nil or x!=nil where x is statically known to be nil or non-nil. These are often a mistake, especially in control flow related to errors. Panics with nil values are checked because they are not detectable by
if r := recover(); r != nil {
This check reports conditions such as:
if f == nil { // impossible condition (f is a function)
}
and:
p := &v
...
if p != nil { // tautological condition
}
and:
if p == nil {
print(*p) // nil dereference
}
and:
if p == nil {
panic(p)
}
Sometimes the control flow may be quite complex, making bugs hard to spot. In the example below, the err.Error expression is guaranteed to panic because, after the first return, err must be nil. The intervening loop is just a distraction.
...
err := g.Wait()
if err != nil {
return err
}
partialSuccess := false
for _, err := range errs {
if err == nil {
partialSuccess = true
break
}
}
if partialSuccess {
reportStatus(StatusMessage{
Code: code.ERROR,
Detail: err.Error(), // "nil dereference in dynamic method call"
})
return nil
}
...
Default: on.
Package documentation: [nilness](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/nilness)
## `nonewvars`: suggested fixes for "no new vars on left side of :="
This checker provides suggested fixes for type errors of the type "no new vars on left side of :=". For example:
z := 1
z := 2
will turn into
z := 1
z = 2
Default: on.
Package documentation: [nonewvars](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/nonewvars)
## `noresultvalues`: suggested fixes for unexpected return values
This checker provides suggested fixes for type errors of the type "no result values expected" or "too many return values". For example:
func z() { return nil }
will turn into
func z() { return }
Default: on.
Package documentation: [noresultvalues](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/noresultvalues)
## `omitzero`: suggest replacing omitempty with omitzero for struct fields
The omitzero analyzer identifies uses of the \`omitempty\` JSON struct tag on fields that are themselves structs. For struct-typed fields, the \`omitempty\` tag has no effect on the behavior of json.Marshal and json.Unmarshal. The analyzer offers two suggestions: either remove the tag, or replace it with \`omitzero\` (added in Go 1.24), which correctly omits the field if the struct value is zero.
However, some other serialization packages (notably kubebuilder, see [https://book.kubebuilder.io/reference/markers.html](https://book.kubebuilder.io/reference/markers.html)) may have their own interpretation of the \`json:",omitzero"\` tag, so removing it may affect program behavior. For this reason, the omitzero modernizer will not make changes in any package that contains +kubebuilder annotations.
Replacing \`omitempty\` with \`omitzero\` is a change in behavior. The original code would always encode the struct field, whereas the modified code will omit it if it is a zero-value.
Default: on.
Package documentation: [omitzero](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#omitzero)
## `plusbuild`: remove obsolete //+build comments
The plusbuild analyzer suggests a fix to remove obsolete build tags of the form:
//+build linux,amd64
in files that also contain a Go 1.18-style tag such as:
//go:build linux && amd64
(It does not check that the old and new tags are consistent; that is the job of the 'buildtag' analyzer in the vet suite.)
Default: on.
Package documentation: [plusbuild](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#plusbuild)
## `printf`: check consistency of Printf format strings and arguments
The check applies to calls of the formatting functions such as [fmt.Printf](/fmt#Printf) and [fmt.Sprintf](/fmt#Sprintf), as well as any detected wrappers of those functions such as [log.Printf](/log#Printf). It reports a variety of mistakes such as syntax errors in the format string and mismatches (of number and type) between the verbs and their arguments.
See the documentation of the fmt package for the complete set of format operators and their operand types.
Default: on.
Package documentation: [printf](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/printf)
## `rangeint`: replace 3-clause for loops with for-range over integers
The rangeint analyzer suggests replacing traditional for loops such as
for i := 0; i < n; i++ { ... }
with the more idiomatic Go 1.22 style:
for i := range n { ... }
This transformation is applied only if (a) the loop variable is not modified within the loop body and (b) the loop's limit expression is not modified within the loop, as \`for range\` evaluates its operand only once.
Default: on.
Package documentation: [rangeint](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#rangeint)
## `recursiveiter`: check for inefficient recursive iterators
This analyzer reports when a function that returns an iterator (iter.Seq or iter.Seq2) calls itself as the operand of a range statement, as this is inefficient.
When implementing an iterator (e.g. iter.Seq\[T]) for a recursive data type such as a tree or linked list, it is tempting to recursively range over the iterator for each child element.
Here's an example of a naive iterator over a binary tree:
type tree struct {
value int
left, right *tree
}
func (t *tree) All() iter.Seq[int] {
return func(yield func(int) bool) {
if t != nil {
for elem := range t.left.All() { // "inefficient recursive iterator"
if !yield(elem) {
return
}
}
if !yield(t.value) {
return
}
for elem := range t.right.All() { // "inefficient recursive iterator"
if !yield(elem) {
return
}
}
}
}
}
Though it correctly enumerates the elements of the tree, it hides a significant performance problem--two, in fact. Consider a balanced tree of N nodes. Iterating the root node will cause All to be called once on every node of the tree. This results in a chain of nested active range-over-func statements when yield(t.value) is called on a leaf node.
The first performance problem is that each range-over-func statement must typically heap-allocate a variable, so iteration of the tree allocates as many variables as there are elements in the tree, for a total of O(N) allocations, all unnecessary.
The second problem is that each call to yield for a leaf of the tree causes each of the enclosing range loops to receive a value, which they then immediately pass on to their respective yield function. This results in a chain of log(N) dynamic yield calls per element, a total of O(N\*log N) dynamic calls overall, when only O(N) are necessary.
A better implementation strategy for recursive iterators is to first define the "every" operator for your recursive data type, where every(f) reports whether an arbitrary predicate f(x) is true for every element x in the data type. For our tree, the every function would be:
func (t *tree) every(f func(int) bool) bool {
return t == nil ||
t.left.every(f) && f(t.value) && t.right.every(f)
}
For example, this use of the every operator prints whether every element in the tree is an even number:
even := func(x int) bool { return x&1 == 0 }
println(t.every(even))
Then the iterator can be simply expressed as a trivial wrapper around the every operator:
func (t *tree) All() iter.Seq[int] {
return func(yield func(int) bool) {
_ = t.every(yield)
}
}
In effect, tree.All computes whether yield returns true for each element, short-circuiting if it ever returns false, then discards the final boolean result.
This has much better performance characteristics: it makes one dynamic call per element of the tree, and it doesn't heap-allocate anything. It is also clearer.
Default: on.
Package documentation: [recursiveiter](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/recursiveiter)
## `reflecttypefor`: replace reflect.TypeOf(x) with TypeFor[T]()
This analyzer suggests fixes to replace uses of reflect.TypeOf(x) with reflect.TypeFor, introduced in go1.22, when the desired runtime type is known at compile time, for example:
reflect.TypeOf(uint32(0)) -> reflect.TypeFor[uint32]()
reflect.TypeOf((*ast.File)(nil)) -> reflect.TypeFor[*ast.File]()
It also offers a fix to simplify the construction below, which uses reflect.TypeOf to return the runtime type for an interface type,
reflect.TypeOf((*io.Reader)(nil)).Elem()
to:
reflect.TypeFor[io.Reader]()
No fix is offered in cases when the runtime type is dynamic, such as:
var r io.Reader = ...
reflect.TypeOf(r)
or when the operand has potential side effects.
Default: on.
Package documentation: [reflecttypefor](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#reflecttypefor)
## `shadow`: check for possible unintended shadowing of variables
This analyzer check for shadowed variables. A shadowed variable is a variable declared in an inner scope with the same name and type as a variable in an outer scope, and where the outer variable is mentioned after the inner one is declared.
(This definition can be refined; the module generates too many false positives and is not yet enabled by default.)
For example:
func BadRead(f *os.File, buf []byte) error {
var err error
for {
n, err := f.Read(buf) // shadows the function variable 'err'
if err != nil {
break // causes return of wrong value
}
foo(buf)
}
return err
}
Default: off. Enable by setting `"analyses": {"shadow": true}`.
Package documentation: [shadow](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/shadow)
## `shift`: check for shifts that equal or exceed the width of the integer
Default: on.
Package documentation: [shift](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/shift)
## `sigchanyzer`: check for unbuffered channel of os.Signal
This checker reports call expression of the form
signal.Notify(c <-chan os.Signal, sig ...os.Signal),
where c is an unbuffered channel, which can be at risk of missing the signal.
Default: on.
Package documentation: [sigchanyzer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sigchanyzer)
## `simplifycompositelit`: check for composite literal simplifications
An array, slice, or map composite literal of the form:
[]T{T{}, T{}}
will be simplified to:
[]T{{}, {}}
This is one of the simplifications that "gofmt -s" applies.
This analyzer ignores generated code.
Default: on.
Package documentation: [simplifycompositelit](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifycompositelit)
## `simplifyrange`: check for range statement simplifications
A range of the form:
for x, _ = range v {...}
will be simplified to:
for x = range v {...}
A range of the form:
for _ = range v {...}
will be simplified to:
for range v {...}
This is one of the simplifications that "gofmt -s" applies.
This analyzer ignores generated code.
Default: on.
Package documentation: [simplifyrange](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyrange)
## `simplifyslice`: check for slice simplifications
A slice expression of the form:
s[a:len(s)]
will be simplified to:
s[a:]
This is one of the simplifications that "gofmt -s" applies.
This analyzer ignores generated code.
Default: on.
Package documentation: [simplifyslice](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifyslice)
## `slicescontains`: replace loops with slices.Contains or slices.ContainsFunc
The slicescontains analyzer simplifies loops that check for the existence of an element in a slice. It replaces them with calls to \`slices.Contains\` or \`slices.ContainsFunc\`, which were added in Go 1.21.
If the expression for the target element has side effects, this transformation will cause those effects to occur only once, not once per tested slice element.
Default: on.
Package documentation: [slicescontains](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicescontains)
## `slicesdelete`: replace append-based slice deletion with slices.Delete
The slicesdelete analyzer suggests replacing the idiom
s = append(s[:i], s[j:]...)
with the more explicit
s = slices.Delete(s, i, j)
introduced in Go 1.21.
This analyzer is disabled by default. The \`slices.Delete\` function zeros the elements between the new length and the old length of the slice to prevent memory leaks, which is a subtle difference in behavior compared to the append-based idiom; see [https://go.dev/issue/73686](https://go.dev/issue/73686).
Default: off. Enable by setting `"analyses": {"slicesdelete": true}`.
Package documentation: [slicesdelete](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicesdelete)
## `slicessort`: replace sort.Slice with slices.Sort for basic types
The slicessort analyzer simplifies sorting slices of basic ordered types. It replaces
sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
with the simpler \`slices.Sort(s)\`, which was added in Go 1.21.
Default: on.
Package documentation: [slicessort](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#slicessort)
## `slog`: check for invalid structured logging calls
The slog checker looks for calls to functions from the log/slog package that take alternating key-value pairs. It reports calls where an argument in a key position is neither a string nor a slog.Attr, and where a final key is missing its value. For example,it would report
slog.Warn("message", 11, "k") // slog.Warn arg "11" should be a string or a slog.Attr
and
slog.Info("message", "k1", v1, "k2") // call to slog.Info missing a final value
Default: on.
Package documentation: [slog](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/slog)
## `sortslice`: check the argument type of sort.Slice
sort.Slice requires an argument of a slice type. Check that the interface{} value passed to sort.Slice is actually a slice.
Default: on.
Package documentation: [sortslice](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/sortslice)
## `stditerators`: use iterators instead of Len/At-style APIs
This analyzer suggests a fix to replace each loop of the form:
for i := 0; i < x.Len(); i++ {
use(x.At(i))
}
or its "for elem := range x.Len()" equivalent by a range loop over an iterator offered by the same data type:
for elem := range x.All() {
use(x.At(i)
}
where x is one of various well-known types in the standard library.
Default: on.
Package documentation: [stditerators](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stditerators)
## `stdmethods`: check signature of methods of well-known interfaces
Sometimes a type may be intended to satisfy an interface but may fail to do so because of a mistake in its method signature. For example, the result of this WriteTo method should be (int64, error), not error, to satisfy io.WriterTo:
type myWriterTo struct{...}
func (myWriterTo) WriteTo(w io.Writer) error { ... }
This check ensures that each method whose name matches one of several well-known interface methods from the standard library has the correct signature for that interface.
Checked method names include:
Format GobEncode GobDecode MarshalJSON MarshalXML
Peek ReadByte ReadFrom ReadRune Scan Seek
UnmarshalJSON UnreadByte UnreadRune WriteByte
WriteTo
Default: on.
Package documentation: [stdmethods](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdmethods)
## `stdversion`: report uses of too-new standard library symbols
The stdversion analyzer reports references to symbols in the standard library that were introduced by a Go release higher than the one in force in the referring file. (Recall that the file's Go version is defined by the 'go' directive its module's go.mod file, or by a "//go:build go1.X" build tag at the top of the file.)
The analyzer does not report a diagnostic for a reference to a "too new" field or method of a type that is itself "too new", as this may have false positives, for example if fields or methods are accessed through a type alias that is guarded by a Go version constraint.
Default: on.
Package documentation: [stdversion](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdversion)
## `stringintconv`: check for string(int) conversions
This checker flags conversions of the form string(x) where x is an integer (but not byte or rune) type. Such conversions are discouraged because they return the UTF-8 representation of the Unicode code point x, and not a decimal string representation of x as one might expect. Furthermore, if x denotes an invalid code point, the conversion cannot be statically rejected.
For conversions that intend on using the code point, consider replacing them with string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the string representation of the value in the desired base.
Default: on.
Package documentation: [stringintconv](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stringintconv)
## `stringsbuilder`: replace += with strings.Builder
This analyzer replaces repeated string += string concatenation operations with calls to Go 1.10's strings.Builder.
For example:
var s = "["
for x := range seq {
s += x
s += "."
}
s += "]"
use(s)
is replaced by:
var s strings.Builder
s.WriteString("[")
for x := range seq {
s.WriteString(x)
s.WriteString(".")
}
s.WriteString("]")
use(s.String())
This avoids quadratic memory allocation and improves performance.
The analyzer requires that all references to s except the final one are += operations. To avoid warning about trivial cases, at least one must appear within a loop. The variable s must be a local variable, not a global or parameter.
The sole use of the finished string must be the last reference to the variable s. (It may appear within an intervening loop or function literal, since even s.String() is called repeatedly, it does not allocate memory.)
Often the addend is a call to fmt.Sprintf, as in this example:
var s string
for x := range seq {
s += fmt.Sprintf("%v", x)
}
which, once the suggested fix is applied, becomes:
var s strings.Builder
for x := range seq {
s.WriteString(fmt.Sprintf("%v", x))
}
The WriteString call can be further simplified to the more efficient fmt.Fprintf(&s, "%v", x), avoiding the allocation of an intermediary. However, stringsbuilder does not perform this simplification; it requires staticcheck analyzer QF1012. (See [https://go.dev/issue/76918](https://go.dev/issue/76918).)
Default: on.
Package documentation: [stringsbuilder](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringbuilder)
## `stringscut`: replace strings.Index etc. with strings.Cut
This analyzer replaces certain patterns of use of [strings.Index](/strings#Index) and string slicing by [strings.Cut](/strings#Cut), added in go1.18.
For example:
idx := strings.Index(s, substr)
if idx >= 0 {
return s[:idx]
}
is replaced by:
before, _, ok := strings.Cut(s, substr)
if ok {
return before
}
And:
idx := strings.Index(s, substr)
if idx >= 0 {
return
}
is replaced by:
found := strings.Contains(s, substr)
if found {
return
}
It also handles variants using [strings.IndexByte](/strings#IndexByte) instead of Index, or the bytes package instead of strings.
Fixes are offered only in cases in which there are no potential modifications of the idx, s, or substr expressions between their definition and use.
Default: on.
Package documentation: [stringscut](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringscut)
## `stringscutprefix`: replace HasPrefix/TrimPrefix with CutPrefix
The stringscutprefix analyzer simplifies a common pattern where code first checks for a prefix with \`strings.HasPrefix\` and then removes it with \`strings.TrimPrefix\`. It replaces this two-step process with a single call to \`strings.CutPrefix\`, introduced in Go 1.20. The analyzer also handles the equivalent functions in the \`bytes\` package.
For example, this input:
if strings.HasPrefix(s, prefix) {
use(strings.TrimPrefix(s, prefix))
}
is fixed to:
if after, ok := strings.CutPrefix(s, prefix); ok {
use(after)
}
The analyzer also offers fixes to use CutSuffix in a similar way. This input:
if strings.HasSuffix(s, suffix) {
use(strings.TrimSuffix(s, suffix))
}
is fixed to:
if before, ok := strings.CutSuffix(s, suffix); ok {
use(before)
}
Default: on.
Package documentation: [stringscutprefix](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringscutprefix)
## `stringsseq`: replace ranging over Split/Fields with SplitSeq/FieldsSeq
The stringsseq analyzer improves the efficiency of iterating over substrings. It replaces
for range strings.Split(...)
with the more efficient
for range strings.SplitSeq(...)
which was added in Go 1.24 and avoids allocating a slice for the substrings. The analyzer also handles strings.Fields and the equivalent functions in the bytes package.
Default: on.
Package documentation: [stringsseq](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#stringsseq)
## `structtag`: check that struct field tags conform to reflect.StructTag.Get
Also report certain struct tags (json, xml) used with unexported fields.
Default: on.
Package documentation: [structtag](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/structtag)
## `testingcontext`: replace context.WithCancel with t.Context in tests
The testingcontext analyzer simplifies context management in tests. It replaces the manual creation of a cancellable context,
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
with a single call to t.Context(), which was added in Go 1.24.
This change is only suggested if the \`cancel\` function is not used for any other purpose.
Default: on.
Package documentation: [testingcontext](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#testingcontext)
## `testinggoroutine`: report calls to (*testing.T).Fatal from goroutines started by a test
Functions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and Skip{,f,Now} methods of \*testing.T, must be called from the test goroutine itself. This checker detects calls to these functions that occur within a goroutine started by the test. For example:
func TestFoo(t *testing.T) {
go func() {
t.Fatal("oops") // error: (*T).Fatal called from non-test goroutine
}()
}
Default: on.
Package documentation: [testinggoroutine](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/testinggoroutine)
## `tests`: check for common mistaken usages of tests and examples
The tests checker walks Test, Benchmark, Fuzzing and Example functions checking malformed names, wrong signatures and examples documenting non-existent identifiers.
Please see the documentation for package testing in golang.org/pkg/testing for the conventions that are enforced for Tests, Benchmarks, and Examples.
Default: on.
Package documentation: [tests](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/tests)
## `timeformat`: check for calls of (time.Time).Format or time.Parse with 2006-02-01
The timeformat checker looks for time formats with the 2006-02-01 (yyyy-dd-mm) format. Internationally, "yyyy-dd-mm" does not occur in common calendar date standards, and so it is more likely that 2006-01-02 (yyyy-mm-dd) was intended.
Default: on.
Package documentation: [timeformat](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/timeformat)
## `unmarshal`: report passing non-pointer or non-interface values to unmarshal
The unmarshal analysis reports calls to functions such as json.Unmarshal in which the argument type is not a pointer or an interface.
Default: on.
Package documentation: [unmarshal](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unmarshal)
## `unreachable`: check for unreachable code
The unreachable analyzer finds statements that execution can never reach because they are preceded by a return statement, a call to panic, an infinite loop, or similar constructs.
Default: on.
Package documentation: [unreachable](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unreachable)
## `unsafefuncs`: replace unsafe pointer arithmetic with function calls
The unsafefuncs analyzer simplifies pointer arithmetic expressions by replacing them with calls to helper functions such as unsafe.Add, added in Go 1.17.
Example:
unsafe.Pointer(uintptr(ptr) + uintptr(n))
where ptr is an unsafe.Pointer, is replaced by:
unsafe.Add(ptr, n)
Default: on.
Package documentation: [unsafefuncs](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#unsafefuncs)
## `unsafeptr`: check for invalid conversions of uintptr to unsafe.Pointer
The unsafeptr analyzer reports likely incorrect uses of unsafe.Pointer to convert integers to pointers. A conversion from uintptr to unsafe.Pointer is invalid if it implies that there is a uintptr-typed word in memory that holds a pointer value, because that word will be invisible to stack copying and to the garbage collector.
Default: on.
Package documentation: [unsafeptr](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unsafeptr)
## `unusedfunc`: check for unused functions, methods, etc
The unusedfunc analyzer reports functions and methods that are never referenced outside of their own declaration.
A function is considered unused if it is unexported and not referenced (except within its own declaration).
A method is considered unused if it is unexported, not referenced (except within its own declaration), and its name does not match that of any method of an interface type declared within the same package.
The tool may report false positives in some situations, for example:
- for a declaration of an unexported function that is referenced from another package using the go:linkname mechanism, if the declaration's doc comment does not also have a go:linkname comment.
(Such code is in any case strongly discouraged: linkname annotations, if they must be used at all, should be used on both the declaration and the alias.)
- for compiler intrinsics in the "runtime" package that, though never referenced, are known to the compiler and are called indirectly by compiled object code.
- for functions called only from assembly.
- for functions called only from files whose build tags are not selected in the current build configuration.
Since these situations are relatively common in the low-level parts of the runtime, this analyzer ignores the standard library. See [https://go.dev/issue/71686](https://go.dev/issue/71686) and [https://go.dev/issue/74130](https://go.dev/issue/74130) for further discussion of these limitations.
The unusedfunc algorithm is not as precise as the golang.org/x/tools/cmd/deadcode tool, but it has the advantage that it runs within the modular analysis framework, enabling near real-time feedback within gopls.
The unusedfunc analyzer also reports unused types, vars, and constants. Enums--constants defined with iota--are ignored since even the unused values must remain present to preserve the logical ordering.
Default: on.
Package documentation: [unusedfunc](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedfunc)
## `unusedparams`: check for unused parameters of functions
The unusedparams analyzer checks functions to see if there are any parameters that are not being used.
To ensure soundness, it ignores:
- "address-taken" functions, that is, functions that are used as a value rather than being called directly; their signatures may be required to conform to a func type.
- exported functions or methods, since they may be address-taken in another package.
- unexported methods whose name matches an interface method declared in the same package, since the method's signature may be required to conform to the interface type.
- functions with empty bodies, or containing just a call to panic.
- parameters that are unnamed, or named "\_", the blank identifier.
The analyzer suggests a fix of replacing the parameter name by "\_", but in such cases a deeper fix can be obtained by invoking the "Refactor: remove unused parameter" code action, which will eliminate the parameter entirely, along with all corresponding arguments at call sites, while taking care to preserve any side effects in the argument expressions; see [https://github.com/golang/tools/releases/tag/gopls%2Fv0.14](https://github.com/golang/tools/releases/tag/gopls%2Fv0.14).
This analyzer ignores generated code.
Default: on.
Package documentation: [unusedparams](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedparams)
## `unusedresult`: check for unused results of calls to some functions
Some functions like fmt.Errorf return a result and have no side effects, so it is always a mistake to discard the result. Other functions may return an error that must not be ignored, or a cleanup operation that must be called. This analyzer reports calls to functions like these when the result of the call is ignored.
The set of functions may be controlled using flags.
Default: on.
Package documentation: [unusedresult](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedresult)
## `unusedvariable`: check for unused variables and suggest fixes
Default: on.
Package documentation: [unusedvariable](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedvariable)
## `unusedwrite`: checks for unused writes
The analyzer reports instances of writes to struct fields and arrays that are never read. Specifically, when a struct object or an array is copied, its elements are copied implicitly by the compiler, and any element write to this copy does nothing with the original object.
For example:
type T struct { x int }
func f(input []T) {
for i, v := range input { // v is a copy
v.x = i // unused write to field x
}
}
Another example is about non-pointer receiver:
type T struct { x int }
func (t T) f() { // t is a copy
t.x = i // unused write to field x
}
Default: on.
Package documentation: [unusedwrite](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedwrite)
## `waitgroup`: check for misuses of sync.WaitGroup
This analyzer detects mistaken calls to the (\*sync.WaitGroup).Add method from inside a new goroutine, causing Add to race with Wait:
// WRONG
var wg sync.WaitGroup
go func() {
wg.Add(1) // "WaitGroup.Add called from inside new goroutine"
defer wg.Done()
...
}()
wg.Wait() // (may return prematurely before new goroutine starts)
The correct code calls Add before starting the goroutine:
// RIGHT
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
...
}()
wg.Wait()
Default: on.
Package documentation: [waitgroup](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/waitgroup)
## `waitgroup`: replace wg.Add(1)/go/wg.Done() with wg.Go
The waitgroup analyzer simplifies goroutine management with \`sync.WaitGroup\`. It replaces the common pattern
wg.Add(1)
go func() {
defer wg.Done()
...
}()
with a single call to
wg.Go(func(){ ... })
which was added in Go 1.25.
Default: on.
Package documentation: [waitgroup](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/modernize#waitgroup)
## `yield`: report calls to yield where the result is ignored
After a yield function returns false, the caller should not call the yield function again; generally the iterator should return promptly.
This example fails to check the result of the call to yield, causing this analyzer to report a diagnostic:
yield(1) // yield may be called again (on L2) after returning false
yield(2)
The corrected code is either this:
if yield(1) { yield(2) }
or simply:
_ = yield(1) && yield(2)
It is not always a mistake to ignore the result of yield. For example, this is a valid single-element iterator:
yield(1) // ok to ignore result
return
It is only a mistake when the yield call that returned false may be followed by another call.
Default: on.
Package documentation: [yield](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/yield)
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/codelenses.md
---
title: "Gopls: Code lenses"
---
A "code lens" is a command associated with a range of a source file.
The VS Code manual describes code lenses as
"[actionable, contextual information, interspersed in your source
code](https://code.visualstudio.com/blogs/2017/02/12/code-lens-roundup)".
The LSP [`textDocument/codeLens`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeLens) operation requests the
current set of code lenses for a file.
Gopls generates code lenses from a number of sources.
This document describes them.
They can be enabled and disabled using the
[`codelenses`](settings.md#codelenses) setting.
Their features are subject to change.
Client support:
- **VS Code**: Code Lenses appear as small text links above a line of source code.
- **Emacs + eglot**: Not supported, but prototype exists at https://github.com/joaotavora/eglot/pull/71.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls codelens`. For example, `gopls codelens -exec file.go:123 "run test"` runs the test at the specified line.
## `generate`: Run `go generate`
This codelens source annotates any `//go:generate` comments
with commands to run `go generate` in this directory, on
all directories recursively beneath this one.
See [Generating code](https://go.dev/blog/generate) for
more details.
Default: on
File type: Go
## `regenerate_cgo`: Re-generate cgo declarations
This codelens source annotates an `import "C"` declaration
with a command to re-run the [cgo
command](https://pkg.go.dev/cmd/cgo) to regenerate the
corresponding Go declarations.
Use this after editing the C code in comments attached to
the import, or in C header files included by it.
Default: on
File type: Go
## `test`: Run tests and benchmarks
This codelens source annotates each `Test` and `Benchmark`
function in a `*_test.go` file with a command to run it.
This source is off by default because VS Code has
a client-side custom UI for testing, and because progress
notifications are not a great UX for streamed test output.
See:
- golang/go#67400 for a discussion of this feature.
- https://github.com/joaotavora/eglot/discussions/1402
for an alternative approach.
Default: off
File type: Go
## `run_govulncheck`: Run govulncheck (legacy)
This codelens source annotates the `module` directive in a go.mod file
with a command to run Govulncheck asynchronously.
[Govulncheck](https://go.dev/blog/vuln) is a static analysis tool that
computes the set of functions reachable within your application, including
dependencies; queries a database of known security vulnerabilities; and
reports any potential problems it finds.
Default: on
File type: go.mod
## `tidy`: Tidy go.mod file
This codelens source annotates the `module` directive in a
go.mod file with a command to run [`go mod
tidy`](https://go.dev/ref/mod#go-mod-tidy), which ensures
that the go.mod file matches the source code in the module.
Default: on
File type: go.mod
## `upgrade_dependency`: Update dependencies
This codelens source annotates the `module` directive in a
go.mod file with commands to:
- check for available upgrades,
- upgrade direct dependencies, and
- upgrade all dependencies transitively.
Default: on
File type: go.mod
## `vendor`: Update vendor directory
This codelens source annotates the `module` directive in a
go.mod file with a command to run [`go mod
vendor`](https://go.dev/ref/mod#go-mod-vendor), which
creates or updates the directory named `vendor` in the
module root so that it contains an up-to-date copy of all
necessary package dependencies.
Default: on
File type: go.mod
## `vulncheck`: Run govulncheck
**This setting is experimental and may be deleted.**
This codelens source annotates the `module` directive in a go.mod file
with a command to run govulncheck synchronously.
[Govulncheck](https://go.dev/blog/vuln) is a static analysis tool that
computes the set of functions reachable within your application, including
dependencies; queries a database of known security vulnerabilities; and
reports any potential problems it finds.
Default: off
File type: go.mod
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/command-line.md
---
title: "Gopls: Command-line interface"
---
The `gopls` command provides a number of subcommands that expose much
of the server's functionality. However, the interface is currently
**experimental** and **subject to change at any point.**
It is not efficient, complete, flexible, or officially supported.
Its primary use is as a debugging aid.
For example, this command reports the location of references to the
symbol at the specified file/line/column:
```
$ gopls references ./gopls/main.go:35:8
Log: Loading packages...
Info: Finished loading packages.
/home/gopher/xtools/go/packages/gopackages/main.go:27:7-11
/home/gopher/xtools/gopls/internal/cmd/integration_test.go:1062:7-11
/home/gopher/xtools/gopls/internal/test/integration/bench/bench_test.go:59:8-12
/home/gopher/xtools/gopls/internal/test/integration/regtest.go:140:8-12
/home/gopher/xtools/gopls/main.go:35:7-11
```
See https://go.dev/issue/63693 for a discussion of its future.
Learn about available commands and flags by running `gopls help`.
Positions within files are specified as `file.go:line:column` triples,
where the line and column start at 1, and columns are measured in
bytes of the UTF-8 encoding.
Alternatively, positions may be specified by the byte offset within
the UTF-8 encoding of the file, starting from zero, for example
`file.go:#1234`.
(When working in non-ASCII files, beware that your editor may report a
position's offset within its file using a different measure such as
UTF-16 codes, Unicode code points, or graphemes).
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/contributing.md
---
title: "Gopls: Contributing"
---
Contributions are welcome! However, development is fast moving,
and we are limited in our capacity to review contributions.
So, before sending a CL, please please please:
- **file an issue** for a bug or feature request, if one does not
exist already. This allows us to identify redundant requests, or to
merge a specific problem into a more general one, and to assess the
importance of the problem.
- **claim it for yourself** by commenting on the issue or, if you are
able, by assigning the issue to yourself. This helps us avoid two
people working on the same problem.
- **propose an implementation plan** in the issue tracker for CLs of
any complexity. It is much more efficient to discuss the plan at a
high level before we start getting bogged down in the details of
a code review.
When you send a CL, it should include:
- a **CL description** that summarizes the change,
motivates why it is necessary,
explains it at a high level,
contrasts it with more obvious or simpler approaches, and
links to relevant issues;
- **tests** (integration tests or marker tests);
- **documentation**, for new or modified features; and
- **release notes**, for new features or significant changes.
During code review, please address all reviewer comments.
Some comments result in straightforward code changes;
others demand a more complex response.
When a reviewer asks a question, the best response is
often not to respond to it directly, but to change the
code to avoid raising the question,
for example by making the code self-explanatory.
It's fine to disagree with a comment,
point out a reviewer's mistake,
or offer to address a comment in a follow-up change,
leaving a `TODO` comment in the current CL.
But please don't dismiss or quietly ignore a comment without action,
as it may lead reviewers to repeat themselves,
or to serious problems being neglected.
For more detail, see the Go project's
[contribution guidelines](https://golang.org/doc/contribute.html).
## Finding issues
All `gopls` issues are labeled as such (see the [`gopls` label][issue-gopls]).
Issues that are suitable for contributors are additionally tagged with the
[`help-wanted` label][issue-wanted].
Before you begin working on an issue, please leave a comment that you are
claiming it.
## Getting started
[](https://pkg.go.dev/golang.org/x/tools/gopls/internal)
Most of the `gopls` logic is in the `golang.org/x/tools/gopls/internal` directory.
See [design/implementation.md](./design/implementation.md) for an overview of the code organization.
## Build
To build a version of `gopls` with your changes applied:
```bash
cd /path/to/tools/gopls
go install
```
To confirm that you are testing with the correct `gopls` version, check that
your `gopls` version looks like this:
```bash
$ gopls version
golang.org/x/tools/gopls master
golang.org/x/tools/gopls@(devel)
```
## Getting help
The best way to contact the gopls team directly is via the
[#gopls-dev](https://app.slack.com/client/T029RQSE6/CRWSN9NCD) channel on the
gophers slack. Please feel free to ask any questions about your contribution or
about contributing in general.
## Error handling
It is important for the user experience that, whenever practical,
minor logic errors in a particular feature don't cause the server to
crash.
The representation of a Go program is complex. The import graph of
package metadata, the syntax trees of parsed files, and their
associated type information together form a huge API surface area.
Even when the input is valid, there are many edge cases to consider,
and this grows by an order of magnitude when you consider missing
imports, parse errors, and type errors.
What should you do when your logic must handle an error that you
believe "can't happen"?
- If it's possible to return an error, then use the `bug.Errorf`
function to return an error to the user, but also record the bug in
gopls' cache so that it is less likely to be ignored.
- If it's safe to proceed, you can call `bug.Reportf` to record the
error and continue as normal.
- If there's no way to proceed, call `bug.Fatalf` to record the error
and then stop the program with `log.Fatalf`. You can also use
`bug.Panicf` if there's a chance that a recover handler might save
the situation.
- Only if you can prove locally that an error is impossible should you
call `log.Fatal`. If the error may happen for some input, however
unlikely, then you should use one of the approaches above. Also, if
the proof of safety depends on invariants broadly distributed across
the code base, then you should instead use `bug.Panicf`.
Note also that panicking is preferable to `log.Fatal` because it
allows VS Code's crash reporting to recognize and capture the stack.
Bugs reported through `bug.Errorf` and friends are retrieved using the
`gopls bug` command, which opens a GitHub Issue template and populates
it with a summary of each bug and its frequency.
The text of the bug is rather fastidiously printed to stdout to avoid
sharing user names and error message strings (which could contain
project identifiers) with GitHub.
Users are invited to share it if they are willing.
## Testing
The normal command you should use to run the tests after a change is:
```bash
gopls$ go test -short ./...
```
(The `-short` flag skips some slow-running ones. The trybot builders
run the complete set, on a wide range of platforms.)
Gopls tests are a mix of two kinds.
- [Marker tests](https://golang.org/x/tools/gopls/internal/test/marker) express each test scenario
in a standalone text file that contains the target .go, go.mod, and
go.work files, in which special annotations embedded in comments
drive the test. These tests are generally easy to write and fast
to iterate, but have limitations on what they can express.
- [Integration tests](https://golang.org/x/tools/gopls/internal/test/integration) are regular Go
`func Test(*testing.T)` functions that make a series of calls to an
API for a fake LSP-enabled client editor. The API allows you to open
and edit a file, navigate to a definition, invoke other LSP
operations, and assert properties about the state.
Due to the asynchronous nature of the LSP, integration tests make
assertions about states that the editor must achieve eventually,
even when the program goes wrong quickly, it may take a while before
the error is reported as a failure to achieve the desired state
within several minutes. We recommend that you set
`GOPLS_INTEGRATION_TEST_TIMEOUT=10s` to reduce the timeout for
integration tests when debugging.
When they fail, the integration tests print the log of the LSP
session between client and server. Though verbose, they are very
helpful for debugging once you know how to read them.
Don't hesitate to [reach out](#getting-help) to the gopls team if you
need help.
### CI
When you mail your CL and you or a fellow contributor assigns the
`Run-TryBot=1` label in Gerrit, the
[TryBots](https://golang.org/doc/contribute.html#trybots) will run tests in
both the `golang.org/x/tools` and `golang.org/x/tools/gopls` modules, as
described above.
Furthermore, an additional "gopls-CI" pass will be run by _Kokoro_, which is a
Jenkins-like Google infrastructure for running Dockerized tests. This allows us
to run gopls tests in various environments that would be difficult to add to
the TryBots. Notably, Kokoro runs tests on
[older Go versions](index.md#supported-go-versions) that are no longer supported
by the TryBots. Per that policy, support for these older Go versions is
best-effort, and test failures may be skipped rather than fixed.
Kokoro runs are triggered by the `Run-TryBot=1` label, just like TryBots, but
unlike TryBots they do not automatically re-run if the "gopls-CI" result is
removed in Gerrit. To force a re-run of the Kokoro CI on a CL containing the
`Run-TryBot=1` label, you can reply in Gerrit with the comment "kokoro rerun".
## Debugging
The easiest way to debug your change is to run a single `gopls` test with a
debugger.
See also [Troubleshooting](troubleshooting.md#troubleshooting).
[issue-gopls]: https://github.com/golang/go/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3Agopls "gopls issues"
[issue-wanted]: https://github.com/golang/go/issues?utf8=✓&q=is%3Aissue+is%3Aopen+label%3Agopls+label%3A"help+wanted" "help wanted"
## Documentation
Each CL that adds or changes a feature should include, in addition to
a test that exercises the new behavior:
- a **release note** that briefly explains the change, and
- **comprehensive documentation** in the [index of features](features/).
The release note should go in the file named for the forthcoming
release, for example [release/v0.16.0.md](release/v0.16.0.md). (Create
the file if your feature is the first to be added after a release.)
## Design documentation
* [Integrating `gopls` with an editor](design/integrating.md)
* [Design requirements and decisions](design/design.md)
* [Implementation overview](design/implementation.md)
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/daemon.md
---
title: "Gopls: Running as a daemon"
---
**Note: this feature is new. If you encounter bugs, please [file an
issue](troubleshooting.md#file-an-issue).**
If you just want to try this out, skip ahead to the [quickstart](#quickstart).
## Background: gopls execution modes
Gopls was originally implemented as an LSP sidecar: a process started by
editors or editor plugins, and communicated with using jsonrpc 2.0 over
stdin/stdout. By executing as a stateful process, gopls can maintain a
significant amount of cache and can eagerly perform analysis on the source code
being edited.
This execution mode does not work as well when there are many separate editor
processes or when editor processes are short-lived, as is often the case for
users of non-IDE editors such as Vim or Emacs. Having many processes means
having many caches, consuming a significant amount of system resources. Using
short-lived sessions means paying a start-up cost each time a session is
created.
To support these types of workflows, a new mode of gopls execution is supported
wherein a single, persistent, shared gopls "daemon" process is responsible for
managing all gopls sessions. In this mode, editors still start a gopls sidecar,
but this sidecar merely acts as a thin "forwarder", responsible for forwarding
the LSP to the shared gopls instance and recording metrics, logs, and rpc
traces.
## Quickstart
To use a shared gopls instance you must either manage the daemon process
yourself, or let the gopls forwarder processes start the shared daemon as
needed.
### Running with `-remote=auto`
Automatic management of the daemon is easiest, and can be done by passing the
flag `-remote=auto` to the gopls process started by your editor. This will
cause this process to auto-start the gopls daemon if needed, connect to it, and
forward the LSP. For example, here is a reasonable gopls invocation, that sets
some additional flags for easier [debugging](#debugging):
```bash
gopls -remote=auto -logfile=auto -debug=:0 -remote.debug=:0 -rpc.trace
```
Note that the shared gopls process will automatically shut down after one
minute with no connected clients.
### Managing the daemon manually
To manage the gopls daemon process via external means rather than having the
forwarders manage it, you must start a gopls daemon process with the
`-listen=` flag, and then pass `-remote=` to the gopls processes
started by your editor.
For example, to host the daemon on the TCP port `37374`, do:
```bash
gopls -listen=:37374 -logfile=auto -debug=:0
```
And then from the editor, run
```bash
gopls -remote=:37374 -logfile=auto -debug=:0 -rpc.trace
```
If you are on a POSIX system, you can also use unix domain sockets by prefixing
the flag values with `unix;`. For example:
```bash
gopls -listen="unix;/tmp/gopls-daemon-socket" -logfile=auto -debug=:0
```
And connect via:
```bash
gopls -remote="unix;/tmp/gopls-daemon-socket" -logfile=auto -debug=:0 -rpc.trace
```
(Note that these flag values MUST be enclosed in quotes, because ';' is a
special shell character. For this reason, this syntax is subject to change in
the future.)
## Debugging
Debugging a shared gopls session is more complicated than a singleton session,
because there are now two gopls processes involved with handling the LSP. Here
are some tips:
### Finding logfiles and debug addresses
When running in daemon mode, you can use the `gopls inspect sessions` command
to find the logfile and debug port for your gopls daemon instance (as well as
for all its connected clients). By default, this inspects the default daemon
(i.e. `-remote=auto`). To inspect a different daemon, use the `-remote` flag
explicitly: `gopls -remote=localhost:12345 inspect sessions`.
This works whether or not you have enabled `-remote.debug`.
### Traversing debug pages
When `-debug=:0` is passed to gopls, it runs a webserver that serves stateful
debug pages (see [troubleshooting.md](troubleshooting.md)). You can find the
actual port hosting these pages by either using the `gopls inspect sessions`
command, or by checking the start of the logfile -- it will be one of the first
log messages. For example, if using `-logfile=auto`, find the debug address by
checking `head /tmp/gopls-.log`.
By default, the gopls daemon is not started with `-debug`. To enable it, set
the `-remote.debug` flag on the forwarder instance, so that it invokes gopls
with `-debug` when starting the daemon.
The debug pages of the forwarder process will have a link to the debug pages of
the daemon server process. Correspondingly, the debug pages of the daemon
process will have a link to each of its clients.
This can help you find metrics, traces, and log files for all of the various
servers and clients.
### Using logfiles
The gopls daemon is started with logging disabled by default. To customize
this, pass `-remote.logfile` to the gopls forwarder. Using
`-remote.logfile=auto`, the daemon will log to a default location (on posix
systems: `/tmp/gopls-daemon-.log`).
The gopls daemon does not log session-scoped messages: those are instead
reflected back to the forwarder so that they can be accessed by the editor.
Daemon logs will only contain global messages, for example logs when sessions
connect and disconnect.
It is recommended to start the forwarder gopls process with `-rpc.trace`, so
that its logfile will contain rpc trace logs specific to the LSP session.
## Using multiple shared gopls instances
There may be environments where it is desirable to have more than one shared
gopls instance. If managing the daemon manually, this can be done by simply
choosing different `-listen` addresses for each distinct daemon process.
On POSIX systems, there is also support for automatic management of distinct
shared gopls processes: distinct daemons can be selected by passing
`-remote="auto;"`. Any gopls forwarder passing the same value for ``
will use the same shared daemon.
## FAQ
**Q: Why am I not saving as much memory as I expected when using a shared gopls?**
A: As described in [implementation.md](design/implementation.md), gopls has a
concept of view/session/cache. Each session and view map onto exactly one
editor session (because they contain things like edited but unsaved buffers).
The cache contains things that are independent of any editor session, and can
therefore be shared.
When, for example, three editor session are sharing a single gopls process,
they will share the cache but will each have their own session and view. The
memory savings in this mode, when compared to three separate gopls processes,
corresponds to the amount of cache overlap across sessions.
Because this hasn't mattered much in the past, it is likely that there is state
that can be moved out of the session/view, and into the cache, thereby
increasing the amount of memory savings in the shared mode.
**Q: How do I customize the daemon instance when using `-remote=auto`?**
The daemon may be customized using flags of the form `-remote.*` on the
forwarder gopls. This causes the forwarder to invoke gopls with these settings
when starting the daemon. As of writing, we expose the following configuration:
* `-remote.logfile`: the location of the daemon logfile
* `-remote.debug`: the daemon's debug address
* `-remote.listen.timeout`: the amount of time the daemon should wait for new
connections while there are no current connections, before shutting down.
Must be set to a valid `time.Duration` (e.g. `30s` or `5m`). If `0`, listen
indefinitely. Default: `1m`.
Note that once the daemon is already running, setting these flags will not
change its configuration. These flags only matter for the forwarder process
that actually starts the daemon.
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/design/design.md
---
title: "Gopls: Design"
---
## _A note from the future_
What follows below is the original design document for gopls, aggregated from
various sources spanning 2018 and 2019. Since then, all of the features listed
below have been implemented, along with many others. The first two goals have
been achieved: gopls is a full implementation of the LSP, and the default
backend for VS Code Go and many other editors. The third goal has only been
partially realized: while gopls has gained many features, it is not extensible
in the sense used in this document: the only way to extend gopls is to modify
gopls. The fourth goal is not achieved: while some notable companies are able
to use gopls with Bazel, the experience is subpar, and the Go command is the
only officially supported build system.
On the other hand, two of the explicit non-goals have been reconsidered. One is
minor: syntax highlighting is now supported in the LSP by way of semantic
tokens. The other is major: as gopls gained popularity, it became apparent that
its memory footprint was a problem. The size of developer workspaces was
increasing faster than the RAM available in typically development environments
(particularly with containerized development). Gopls now uses a hybrid of
on-disk indexes and in-memory caches, described in more detail in our
[blog post on scalability](https://go.dev/blog/gopls-scalability).
Notably, in anticipating difficulties this doc turned out to be prescient.
Gopls has indeed struggled against the core standary library packages upon
which it is built, and its user experience is still limited by the LSP.
Nevertheless, sticking with the standard library and LSP was the right
approach, as despite our small team these decisions have helped gopls keep up
with the evolving Go language (i.e. generics), and to integrate with many new
text editors.
Gopls development continues, more than four years later, with a focus on
simplicity, reliability, and extensibility. The new, opt-in
[Go telemetry](https://github.com/golang/tools/releases/tag/gopls%2Fv0.14.0)
will help us attain a higher standard of stability in our releases than we've
been able to achieve through Github issues alone. Furthermore, telemetry will
allow us to focus on high-priority features, and deprecate historical
workarounds that burden the codebase. With greater velocity, we look forward
to working with the community on improved refactoring, static analysis, and
whatever else the future brings.
- _Rob Findley (rfindley@google.com), 2023_
## Goals
* `gopls` should **become the default editor backend** for the major editors used by Go programmers, fully supported by the Go team.
* `gopls` will be a **full implementation of LSP**, as described in the [LSP specification], to standardize as many of its features as possible.
* `gopls` will be **clean and extensible** so that it can encompass additional features in the future, allowing Go tooling to become best in class once more.
* `gopls` will **support alternate build systems and file layouts**, allowing Go development to be simpler and more powerful in any environment.
## Context
While Go has a number of excellent and useful command-line tools that enhance the developer experience, it has become clear that integrating these tools with IDEs can pose challenges.
Support of these tools has relied on the goodwill of community members, and they have been put under a large burden of support at times as the language, toolchain and environments change. As a result many tools have ceased to work, have had support problems, or become confusing with forks and replacements, or provided an experience that is not as good as it could be.
See the section below on [existing solutions](#existing-solutions) for more problems and details.
This is fine for tools used occasionally, but for core IDE features, this is not acceptable.
Autocompletion, jump to definition, formatting, and other such features should always work, as they are key for Go development.
The Go team will create an editor backend that works in any build system.
It will also be able to improve upon the latency of Go tools, since each tool will no longer have to individually run the type-checker on each invocation, instead there will be a long-running process and data can be shared between the definitions, completions, diagnostics, and other features.
By taking ownership of these tools and packaging them together in the form of gopls, the Go team will ensure that the Go development experience isn’t unnecessarily complicated for Go users.
Having one editor backend will simplify the lives of Go developers, the Go team, and the maintainers of Go editor plugins.
See Rebecca's excellent GopherCon keynote [talk] and [slides] for some more context.
## Non-Goals
* Command line speed
Although gopls will have a command line mode, it will be optimized for long running and not command responsiveness, as such it may not be the right tool for things like CI systems.
For such cases there will have to be an alternate tool using the same underlying libraries for consistency.
* Low memory environments
In order to do a good job of processing large projects with very low latencies gopls will be holding a lot of information in memory.
It is presumed that developers are normally working on systems with significant RAM and this will not be a problem.
In general this is upheld by the large memory usage of existing IDE solutions (like IntelliJ)
* Syntax highlighting
At the moment there is no editor that delegates this functionality to a separate binary, and no standard way of doing it.
## Existing solutions
Every year the Go team conducts a survey, asking developers about their experiences with the language.
One question that is asked is “How do you feel about your editor?”.
The responses told a very negative story. Some categorized quotes:
* Setup
* "Hard to install and configure"
* "Inadequate documentation"
* Performance
* "Performance is very poor"
* "Pretty slow in large projects"
* Reliability
* "Features work one day, but not the next"
* "Tooling is not updated with new language features"
Each editor has its own plugin that shells out to a variety of tools, many of which break with new Go releases or because they are no longer maintained.
The individual tools each have to do the work to understand the code and all its transitive dependencies.
Each feature is a different tool, with a different set of patterns for its command line, a different way to accept input and parse output, a different way of specifying source code locations.
To support its existing feature set, VSCode installed 24 different command line tools, many of which have options or forks to configure. When looking at the set of tools that needed to be migrated to modules, across all the editors, there were 63 separate tools.
All these tools need to understand the code, and they use the same standard libraries to do it. Those libraries are optimized for these kinds of tools, but even so processing that much code takes a lot of time time. Almost none of the tools are capable of returning results within 100ms.
As developers type in their editor, multiple of these features need to activate, which means they are not just paying the cost once, but many times. The overall effect is an editing experience that feels sluggish, and features that are either not enabled or sometimes produce results that appear so slowly they are no longer useful when they arrive. This is a problem that increases with the size of the code base, which means it is getting worse over time, and is especially bad for the kinds of large code bases companies are dealing with as they use Go for more major tasks.
## Requirements
### Complete feature set
For gopls to be considered a success it has to implement the full feature set discussed [below](#Features).
This is the set of features that users need in order to feel as productive as they were with the tooling it is replacing. It does not include every feature of previous implementations, there are some features that are almost never used that should be dropped (like guru's pointer analysis) and some other features that do not easily fit and will have to be worked around (replacing the save hook/linter).
### Equivalent or better experience
For all of those features, the user experience must match or exceed the current one available in all editors.
This is an easy statement to make, but a hard one to validate or measure. Many of the possible measures fail to capture the experience.
For instance, if an attempt was made to measure the latency of a jump to definition call, the results would be fairly consistent from the old godef tool. From the gopls implementation there may be a much larger range of latencies, with the best being orders of magnitude faster, and the worse slightly worse, because gopls attempts to do far more work, but manages to cache it across calls.
Or for a completion call, it might be slower but produce a better first match such that users accept it more often, resulting in an overall better experience.
For the most part this has to rely on user reports. If users are refusing to switch because the experience is not better, it is clearly not done, if they are switching but most people are complaining, there are probably enough areas that are better to make the switch compelling but other areas which are worse. If most people are switching and either staying silent or being positive, it is probably done. When writing tools, the user is all that matters.
### Solid community of contributors
The scope and scale of the problem gopls is trying to solve is untenable for the core Go team, it is going to require a strong community to make it all happen.
This implies the code must be easy to contribute to, and easy for many developers to work on in parallel. The functionality needs to be well decoupled, and have a thorough testing story.
### Latencies that fall within user tolerance
There has been a lot of research on acceptable latencies for user actions.
The main result that affects gopls is that feedback in direct response to continuous user actions needs to be under 100ms to be imperceptible, and anything above 200ms aggravates the user.
This means in general the aim has to be <100ms for anything that happens as the developer types.
There will always be cases where gopls fails to meet this deadline, and there needs to be ways to make the user experience okay in those cases, but in general the point of this deadline is to inform the basic architecture design, any solution that cannot theoretically meet this goal in the long term is the wrong answer.
### Easy to configure
Developers are very particular, and have very differing desires in their coding experience. gopls is going to have to support a significant amount of flexibility, in order to meet those desires.
The default settings however with no configuration at all must be the one that is best experience for most users, and where possible the features must be flexible without configuration so that the client can easily make the choices about treatment without changing its communication with gopls.
## Difficulties
### Volume of data
* Small:
* Medium:
* Large:
* Corporate mono-repo: Much much bigger
Parsing and type checking large amounts of code is quite expensive, and the converted forms use a lot of space. As gopls has to keep updating this information while the developer types, it needs to manage how it caches the converted forms very carefully to balance memory use vs speed.
### Cache invalidation
The basic unit of operation for the type checking is the package, but the basic unit of operation for an editor is the file.
gopls needs to be able to map files to packages efficiently, so that when files change it knows which packages need to be updated (along with any other packages that transitively depended on them).
This is made especially difficult by the fact that changing the content of a file can modify which packages it is considered part of (either by changing the package declaration or the build tags), a file can be in more than one package, and changes can be made to files without using the editor, in which case it will not notify us of the changes.
### Inappropriate core functionality
The base libraries for Go (things like [go/token], [go/ast] and [go/types]) are all designed for compiler-like applications.
They tend to worry more about throughput than memory use, they have structures that are intended to grow and then be thrown away at program exit, and they are not designed to keep going in the presence of errors in the source they are handling.
They also have no abilities to do incremental changes.
Making a long running service work well with those libraries is a very large challenge, but writing new libraries would be far more work, and cause a significant long term cost as both sets of libraries would have to be maintained. Right now it is more important to get a working tool into the hands of users. In the long term this decision may have to be revisited, new low level libraries may be the only way to keep pushing the capabilities forwards.
### Build system capabilities
gopls is supposed to be build system agnostic, but it must use the build system to discover how files map to packages. When it tries to do so, even when the functionality is the same, the costs (in time, CPU and memory) are very different, and can significantly impact the user experience. Designing how gopls interacts with the build system to try to minimize or hide these differences is hard.
### Build tags
The build tag system in Go is quite powerful, and has many use cases. Source files can exclude themselves using powerful boolean logic on the set of active tags.
It is however designed for specifying the set of active tags on the command line, and the libraries are all designed to cope with only one valid combination at a time. There is also no way to work out the set of valid combinations.
Type checking a file requires knowledge of all the other files in the same package, and that set of files is modified by the build tags. The set of exported identifiers of a package is also affected by which files are in the package, and thus its build tags.
This means that even for files or packages that have no build tag controls it is not possible to produce correct results without knowing the set of build tags to consider.
This makes it very hard to produce useful results when viewing a file.
### Features not supported by LSP
There are some things it would be good to be able to do that do not fit easily into the existing LSP protocol.
For instance, displaying control flow information, automatic struct tags, complex refactoring...
Each feature will have to be considered carefully, and either propose a change to LSP, or add a way to have gopls specific extensions to the protocol that are still easy to use in all the editor plugins.
To avoid these at the start, only core LSP features will be implemented, as they are sufficient to meet the baseline requirements anyway, but the potential features need to be kept in mind in the core architecture.
### Distribution
Making sure that users are using the right version of gopls is going to be a problem. Each editor plugin is probably going to install the tools in its own way, some will choose to install it system wide, some will keep their own copy.
Because it is a brand new tool, it will be changing rapidly. If users are not informed they are on an old version they will be experiencing problems that have already been fixed, which is worse for them, and then probably reporting them, which wastes time for the gopls team. There needs to be a mechanism for gopls to check if is up to date, and a recommended way to install an up to date version.
### Debugging user problems
gopls is essentially a very stateful long running server on the developer's machine. Its basic operation is affected by many things, from the users environment to the contents of the local build cache. The data it is operating on is often a confidential code base that cannot be shared.
All of these things make it hard for users to report a bug usefully, or create a minimal reproduction.
There needs to be easy ways for users to report what information they can, and ways to attempt to reproduce problems without their entire state. This is also needed to produce regression tests.
## Basic design decisions
There are some fundamental architecture decisions that affect much of the rest of the design of the tool, making fundamental trade offs that impact the user experience.
### Process lifetime: *managed by the editor*
Processing a large code base to fully type check and then analyze it within the latency requirements is not feasible, and is one of the primary problems with the existing solutions. This remains true even if the computed information was cached on disk, as running analyzers and type checkers ends up requiring the full AST of all files in the dependency graph.
It is theoretically possible to do better, but only with a major re-write of the existing parsing and type checking libraries, something that is not feasible at this time.
This implies that gopls should be a long running process, that is able to cache and pre-calculate results in memory so that when a request arrives it can produce the answer much faster.
It could run as a daemon on the user's machine, but there are a lot of issues with managing a daemon. It may well be the right choice in the long term, and it should be allowed for in the fundamental architecture design, but to start with it will instead have a process that lasts as long as the editor that starts it, and that can easily be restarted.
### Caching: *in memory*
Persistent disk caches are very expensive to maintain, and require solving a lot of extra problems.
Although building the information required is expensive compared to the latencies required of the requests, it is fairly minor compared to the startup times of an editor, so it is expected that rebuilding the information when gopls is restarted will be acceptable.
The advantage gained from this is that gopls becomes stateless across restarts which means if it has issues or gets its state confused, a simple restart will often fix the problem.
It also means that when users report problems, the entire state of the on disk cache is not needed to diagnose and reproduce the issue.
### Communication: *stdin/stdout JSON*
The LSP specification defines the JSON messages that are normally used, but it does not define how those message should be sent, and there are implementations of the LSP that do not use JSON (for instance, Protocol buffers are an option).
The constraints on gopls are that it must be easy to integrate into *every editor* on *all operating systems*, and that it should not have large external dependencies.
JSON is part of the Go standard library, and is also the native language of LSP, so it makes the most sense. By far the best supported communication mechanism is the standard input and output of a process, and the common client implementations all have ways of using [JSON rpc 2] in this mode. There were no complete and low dependency implementations of this protocol in Go, but it is a fairly small protocol on top of the JSON library that can be implemented with a moderate effort, and would be a generally useful library to have anyway.
In the future it is expected to run in separated client server mode, so writing it in a way that could use sockets instead of stdin/stdout from the start was the best way to make sure it remained possible. It was also a huge debugging aid to be able to run the gopls server by hand and watch/debug it outside the editor.
### Running other tools: *no*
## Features
There is a set of features that gopls needs to expose to be a comprehensive IDE solution.
The following is the minimum set of features, along with their existing solutions and how they should map to the LSP.
### Introspection
Introspection features tell developers information about their code while they work. They do not make or suggest changes.
---
Diagnostics | Static analysis results of the code, including compilation and lint errors
----------- | ---
Requires | Full go/analysis run, which needs full AST, type and SSA information
LSP | [`textDocument/publishDiagnostics`]
Previous | `go build`, `go vet`, `golint`, [errcheck], [staticcheck]
| | This is one of the most important IDE features, allowing fast turn around without having to run compilers and checkers in the shell. Often used to power problem lists, gutter markers and squiggle underlines in the IDE.
There is some complicated design work to do in order to let users customize the set of checks being run, preferably without having to recompile the main LSP binary.
---
Hover | Information about the code under the cursor.
-------- | ---
Requires | AST and type information for the file and all dependencies
LSP | [`textDocument/hover`]
Previous | [godoc], [gogetdoc]
| | Used when reading code to display information known to the compiler but not always obvious from the code. For instance it may return the types of identifiers, or the documentation.
---
Signature help | Function parameter information and documentation
-------------- | ---
Requires | AST and type information for the file and all dependencies
LSP | [`textDocument/signatureHelp`]
Previous | [gogetdoc]
| | As a function call is being typed into code, it is helpful to know the parameters of that call to enable the developer to call it correctly.
### Navigation
Navigation features are designed to make it easier for a developer to find their way round a code base.
---
Definition | Select an identifier, and jump to the code where that identifier was defined.
---------- | ---
Requires | Full type information for file and all dependencies
LSP | [`textDocument/declaration`]
| | [`textDocument/definition`]
| | [`textDocument/typeDefinition`]
Previous | [godef] |
| | Asking the editor to open the place where a symbol was defined is one of the most commonly used code navigation tools inside an IDE when available. It is especially valuable when exploring an unfamiliar code base.
Due to a limitation of the compiler output, it is not possible to use the binary data for this task (specifically it does not know column information) and thus it must parse from source.
---
Implementation | Reports the types that implement an interface
-------------- | ---
Requires | Full workspace type knowledge
LSP | [`textDocument/implementation`]
Previous | [impl]
| | This feature is hard to scale up to large code bases, and is going to take thought to get right. It may be feasible to implemented a more limited form in the meantime.
---
Document symbols | Provides the set of top level symbols in the current file.
---------------- | ---
Requires | AST of the current file only
LSP | [`textDocument/documentSymbol`]
Previous | [go-outline], [go-symbols]
| | Used to drive things like outline mode.
---
References | Find all references to the symbol under the cursor.
---------- | ---
Requires | AST and type information for the **reverse** transitive closure
LSP | [`textDocument/references`]
Previous | [guru]
| | This requires knowledge of every package that could possible depend on any packages the current file is part of. In the past this has been implemented either by global knowledge, which does not scale, or by specifying a "scope" which confused users to the point where they just did not use the tools. gopls is probably going to need a more powerful solution in the long term, but to start with automatically limiting the scope may produce acceptable results. This would probably be the module if known, or some sensible parent directory otherwise.
---
Folding | Report logical hierarchies of blocks
-------- | ---
Requires | AST of the current file only
LSP | [`textDocument/foldingRange`]
Previous | [go-outline]
| | This is normally used to provide expand and collapse behavior in editors.
---
Selection | Report regions of logical selection around the cursor
--------- | ---
Requires | AST of the current file only
LSP | [`textDocument/selectionRange`]
Previous | [guru]
| | Used in editor features like expand selection.
### Edit assistance
These features suggest or apply edits to the code for the user, including refactoring features, for which there are many potential use cases.
Refactoring is one of the places where Go tools could potentially be very strong, but have not been so far, and thus there is huge potential for improvements in the developer experience.
There is not yet a clear understanding of the kinds of refactoring people need or how they should express them however, and there are weaknesses in the LSP protocol around this.
This means it may be much more of a research project.
---
Format | Fix the formatting of the file
-------- | ---
Requires | AST of current file
LSP | [`textDocument/formatting`]
| | [`textDocument/rangeFormatting`]
| | [`textDocument/onTypeFormatting`]
Previous | [gofmt], [goimports], [goreturns]
| | It will use the standard format package.
Current limitations are that it does not work on malformed code. It may need some very careful changes to the formatter to allow for formatting an invalid AST or changes to force the AST to a valid mode. These changes would improve range and file mode as well, but are basically vital to onTypeFormatting
---
Imports | Rewrite the imports block automatically to match the symbols used.
-------- | ---
Requires | AST of the current file and full symbol knowledge for all candidate packages.
LSP | [`textDocument/codeAction`]
Previous | [goimports], [goreturns]
| | This needs knowledge of packages that are not yet in use, and the ability to find those packages by name.
It also needs exported symbol information for all the packages it discovers.
It should be implemented using the standard imports package, but there may need to be exposed a more fine grained API than just a file rewrite for some of the interactions.
---
Autocompletion | Makes suggestions to complete the entity currently being typed.
-------------- | ---
Requires | AST and type information for the file and all dependencies
Also full exported symbol knowledge for all packages.
LSP | [`textDocument/completion`]
| | [`completionItem/resolve`]
Previous | [gocode]
| | Autocomplete is one of the most complicated features, and the more it knows the better its suggestions can be. For instance it can autocomplete into packages that are not yet being imported if it has their public symbols. It can make better suggestions of options if it knows what kind of program you are writing. It can suggest better arguments if it knows how you normally call a function. It can suggest entire patterns of code if it knows they are common. Unlike many other features, which have a specific task, and once it is doing that task the feature is done, autocomplete will never be finished. Balancing and improving both the candidates and how they are ranked will be a research problem for a long time to come.
---
Rename | Rename an identifier
-------- | ---
Requires | AST and type information for the **reverse** transitive closure
LSP | [`textDocument/rename`]
| | [`textDocument/prepareRename`]
Previous | golang.org/x/tools/cmd/gorename
| | This uses the same information that find references does, with all the same problems and limitations. It is slightly worse because the changes it suggests make it intolerant of incorrect results. It is also dangerous using it to change the public API of a package.
---
Suggested fixes | Suggestions that can be manually or automatically accepted to change the code
--------------- | ---
Requires | Full go/analysis run, which needs full AST, type and SSA information
LSP | [`textDocument/codeAction`]
Previous | N/A
| | This is a brand new feature powered by the new go/analysis engine, and it should allow a huge amount of automated refactoring.
[LSP specification]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/
[talk]: https://www.youtube.com/watch?v=EFJfdWzBHwE
[slides]: https://github.com/gophercon/2019-talks/blob/master/RebeccaStambler-GoPleaseStopBreakingMyEditor/slides.pdf "Go, please stop breaking my editor!"
[JSON rpc 2]: https://www.jsonrpc.org/specification
[errcheck]: https://github.com/kisielk/errcheck
[go-outline]: https://github.com/lukehoban/go-outline
[go-symbols]: https://github.com/acroca/go-symbols
[gocode]: https://github.com/stamblerre/gocode
[godef]: https://github.com/rogpeppe/godef
[godoc]: https://golang.org/cmd/godoc
[gofmt]: https://golang.org/cmd/gofmt
[gogetdoc]: https://github.com/zmb3/gogetdoc
[goimports]: https://pkg.go.dev/golang.org/x/tools/cmd/goimports
[goreturns]: https://github.com/sqs/goreturns
[gotags]: https://github.com/jstemmer/gotags
[guru]: https://pkg.go.dev/golang.org/x/tools/cmd/guru
[impl]: https://github.com/josharian/impl
[staticcheck]: https://staticcheck.io/docs/
[go/types]: https://golang.org/pkg/go/types/
[go/ast]: https://golang.org/pkg/go/ast/
[go/token]: https://golang.org/pkg/go/token/
[`completionItem/resolve`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#completionItem_resolve
[`textDocument/codeAction`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_codeAction
[`textDocument/completion`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_completion
[`textDocument/declaration`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_declaration
[`textDocument/definition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_definition
[`textDocument/documentLink`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentLink
[`textDocument/documentSymbol`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentSymbol
[`textDocument/foldingRange`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_foldingRange
[`textDocument/formatting`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_formatting
[`textDocument/highlight`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_highlight
[`textDocument/hover`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_hover
[`textDocument/implementation`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_implementation
[`textDocument/onTypeFormatting`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_onTypeFormatting
[`textDocument/prepareRename`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_prepareRename
[`textDocument/publishDiagnostics`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_publishDiagnostics
[`textDocument/rangeFormatting`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_rangeFormatting
[`textDocument/references`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_references
[`textDocument/rename`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_rename
[`textDocument/selectionRange`]:https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_selectionRange
[`textDocument/signatureHelp`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_signatureHelp
[`textDocument/typeDefinition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_typeDefinition
[`workspace/didChangeWatchedFiles`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#workspace_didChangeWatchedFiles
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/design/implementation.md
---
title: "Gopls: Implementation"
---
Last major update: Jan 16 2024
This doc presents a high-level overview of the structure of gopls to
help new contributors find their way. It is not intended to be a
complete description of the implementation, nor even of any key
components; for that, the package documentation (linked below) and
other comments within the code are a better guide.
The diagram below shows selected components of the gopls module and
their relationship to each other according to the Go import graph.
Tests and test infrastructure are not shown, nor are utility packages,
nor packages from the [x/tools] module. For brevity, packages are
referred to by their last segment, which is usually unambiguous.
The height of each blob corresponds loosely to its technical depth.
Some blocks are wide and shallow, such as [protocol], which declares
Go types for the entire LSP protocol. Others are deep, such as [cache]
and [golang], as they contain a lot of dense logic and algorithms.

Starting from the bottom, we'll describe the various components.
The lowest layer defines the request and response types of the
Language Server Protocol:
- The [protocol] package defines the standard protocol; it is mostly
generated mechanically from the schema definition provided by
Microsoft.
The most important type is DocumentURI, which represents a `file:`
URL that identifies a client editor document. It also provides
`Mapper`, which maps between the different coordinate systems used
for source positions: UTF-8, UTF-16, and token.Pos.
- The [command] package defines Gopls's non-standard commands, which
are all invoked through the `workspace/executeCommand` extension
mechanism. These commands are typically returned by the server as
continuations of Code Actions or Code Lenses; most clients do not
construct calls to them directly.
The next layer defines a number of important and very widely used data structures:
- The [file] package defines the primary abstractions of a client
file: its `Identity` (URI and content hash), and its `Handle` (which
additionally provides the version and content of a particular
snapshot of the file.
- The [parsego] package defines `File`, the parsed form of a Go source
file, including its content, syntax tree, and coordinary mappings
(Mapper and token.File). The package performs various kinds of tree
repair to work around error-recovery shortcomings of the Go parser.
- The [metadata] package defines `Package`, an abstraction of the
metadata of a Go package, similar to the output of `go list -json`.
Metadata is produced from [go/packages], which takes
care of invoking `go list`. (Users report that it works to some extent
with a GOPACKAGESDRIVER for Bazel, though we maintain no tests for this
scenario.)
The package also provides `Graph`, the complete import graph for a
workspace; each graph node is a `Package`.
The [settings] layer defines the data structure (effectively a large
tree) for gopls configuration options, along with its JSON encoding.
The [cache] layer is the largest and most complex component of gopls.
It is concerned with state management, dependency analysis, and invalidation:
the `Session` of communication with the client;
the `Folder`s that the client has opened;
the `View` of a particular workspace tree with particular build
options;
the `Snapshot` of the state of all files in the workspace after a
particular edit operation;
the contents of all files, whether saved to disk (`DiskFile`) or
edited and unsaved (`Overlay`);
the `Cache` of in-memory memoized computations,
such as parsing go.mod files or build the symbol index;
and the `Package`, which holds the results of type checking a package
from Go syntax.
The cache layer depends on various auxiliary packages, including:
- The [filecache] package, which manages gopls' persistent, transactional,
file-based key/value store.
- The [xrefs], [methodsets], and [typerefs] packages define algorithms
for constructing indexes of information derived from type-checking,
and for encoding and decoding these serializable indexes in the file
cache.
Together these packages enable the fast restart, reduced memory
consumption, and synergy across processes that were delivered by the
v0.12 redesign and described in ["Scaling gopls for the growing Go
ecosystem"](https://go.dev/blog/gopls-scalability).
The cache also defines gopls's [go/analysis] driver, which runs
modular analysis (similar to `go vet`) across the workspace.
Gopls also includes a number of analysis passes that are not part of vet.
The next layer defines four packages, each for handling files in a
particular language:
[mod] for go.mod files;
[work] for go.work files;
[template] for files in `text/template` syntax; and
[golang], for files in Go itself.
This package, by far the largest, provides the main features of gopls:
navigation, analysis, and refactoring of Go code.
As most users imagine it, this package _is_ gopls.
The [server] package defines the LSP service implementation, with one
handler method per LSP request type. Each handler switches on the type
of the file and dispatches to one of the four language-specific
packages.
The [lsprpc] package connects the service interface to our [jsonrpc2](https://www.jsonrpc.org/specification) server.
Bear in mind that the diagram is a dependency graph, a "static"
viewpoint of the program's structure. A more dynamic viewpoint would
order the packages based on the sequence in which they are encountered
during processing of a particular request; in such a view, the bottom
layer would represent the "wire" (protocol and command), the next
layer up would hold the RPC-related packages (lsprpc and server), and
features (e.g. golang, mod, work, template) would be at the top.
The [cmd] package defines the command-line interface of the `gopls`
command, around which gopls's main package is just a trivial wrapper.
It is usually run without arguments, causing it to start a server and
listen indefinitely.
It also provides a number of subcommands that start a server, make a
single request to it, and exit, providing traditional batch-command
access to server functionality. These subcommands are primarily
provided as a debugging aid; but see https://go.dev/issue/63693.
[cache]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache
[cmd]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cmd
[command]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/protocol/command
[debug]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/debug
[file]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/file
[filecache]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/filecache
[go/analysis]: https://pkg.go.dev/golang.org/x/tools@master/go/analysis
[go/packages]: https://pkg.go.dev/golang.org/x/tools@master/go/packages
[gopls]: https://pkg.go.dev/golang.org/x/tools/gopls@master
[jsonrpc]: https://pkg.go.dev/golang.org/x/tools@master/internal/jsonrpc
[jsonrpc2]: https://pkg.go.dev/golang.org/x/tools@master/internal/jsonrpc2
[lsprpc]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/lsprpc
[memoize]: https://github.com/golang/tools/tree/master/internal/memoize
[metadata]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/metadata
[methodsets]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/methodsets
[mod]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/mod
[parsego]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/parsego
[protocol]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/protocol
[server]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/server
[settings]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/settings
[golang]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/golang
[template]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/template
[typerefs]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/typerefs
[work]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/work
[x/tools]: https://github.com/golang/tools@master
[xrefs]: https://pkg.go.dev/golang.org/x/tools/gopls@master/internal/cache/xrefs
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/design/integrating.md
---
title: "Documentation for plugin authors"
---
If you are integrating `gopls` into an editor by writing an editor plugin, there are quite a few semantics of the communication between the editor and `gopls` that are not specified by the [LSP specification].
We attempt to document those details along with any other information that has been helpful to other plugin authors here.
If you are implementing a plugin yourself and have questions this page does not answer, please reach out to us to ask, and then also contribute your findings back to this page.
## Supported features
For the most part you should look at the [Index of features](../features/)
to know whether gopls supports a feature.
For a truly authoritative answer you should check the [result][InitializeResult] of the [initialize] request, where gopls enumerates its support in the [ServerCapabilities].
## Positions and ranges
Many LSP requests pass position or range information. This is described in the [LSP specification][lsp-text-documents]:
> A position inside a document (see Position definition below) is expressed as a zero-based line and character offset. The offsets are based on a UTF-16 string representation. So a string of the form a𐐀b the character offset of the character a is 0, the character offset of 𐐀 is 1 and the character offset of b is 3 since 𐐀 is represented using two code units in UTF-16.
This means that integrators will need to calculate UTF-16 based column offsets.
Use `protocol.Mapper` for all the conversions.
## Edits
In order to deliver changes from gopls to the editor, the LSP supports arrays of [`TextEdit`][lsp-textedit]s in responses.
The spec specifies exactly how these should be applied:
> All text edits ranges refer to positions in the original document. Text edits ranges must never overlap, that means no part of the original document must be manipulated by more than one edit. However, it is possible that multiple edits have the same start position: multiple inserts, or any number of inserts followed by a single remove or replace edit. If multiple inserts have the same position, the order in the array defines the order in which the inserted strings appear in the resulting text.
All `[]TextEdit` are sorted such that applying the array of deltas received in reverse order achieves the desired result that holds with the spec.
## Errors
Various error codes are described in the [LSP specification][lsp-response]. We are still determining what it means for a method to return an error; are errors only for low-level LSP/transport issues or can other conditions cause errors to be returned? See some of this discussion on [#31526].
The method chosen is currently influenced by the exact treatment in the currently popular editor integrations. It may well change, and ideally would become more coherent across requests.
* [`textDocument/codeAction`]: Return error if there was an error computing code actions.
* [`textDocument/completion`]: Log errors, return empty result list.
* [`textDocument/definition`]: Return error if there was an error computing the definition for the position.
* [`textDocument/typeDefinition`]: Return error if there was an error computing the type definition for the position.
* [`textDocument/formatting`]: Return error if there was an error formatting the file.
* [`textDocument/highlight`]: Log errors, return empty result.
* [`textDocument/hover`]: Return empty result.
* [`textDocument/documentLink`]: Log errors, return nil result.
* [`textDocument/publishDiagnostics`]: Log errors if there were any while computing diagnostics.
* [`textDocument/references`]: Log errors, return empty result.
* [`textDocument/rename`]: Return error if there was an error computing renames.
* [`textDocument/signatureHelp`]: Log errors, return nil result.
* [`textDocument/documentSymbols`]: Return error if there was an error computing document symbols.
## Watching files
It is fairly normal for files that affect `gopls` to be modified outside of the editor it is associated with.
For instance, files that are needed to do correct type checking are modified by switching branches in git, or updated by a code generator.
Monitoring files inside gopls directly has a lot of awkward problems, but the [LSP specification] has methods that allow gopls to request that the client notify it of file system changes, specifically [`workspace/didChangeWatchedFiles`].
This is currently being added to gopls by a community member, and tracked in [#31553]
[InitializeResult]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/protocol#InitializeResult
[ServerCapabilities]: https://pkg.go.dev/golang.org/x/tools/gopls/internal/protocol#ServerCapabilities
[`golang.org/x/tools/gopls/internal/protocol`]: https://pkg.go.dev/golang.org/x/tools/internal/protocol#NewPoint
[LSP specification]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/
[lsp-response]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#response-message
[initialize]: https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/#initialize
[lsp-text-documents]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#text-documents
[lsp-textedit]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textedit
[`textDocument/codeAction`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_codeAction
[`textDocument/completion`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_completion
[`textDocument/definition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_definition
[`textDocument/typeDefinition`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_typeDefinition
[`textDocument/formatting`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_formatting
[`textDocument/highlight`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_highlight
[`textDocument/hover`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_hover
[`textDocument/documentLink`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentLink
[`textDocument/publishDiagnostics`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_publishDiagnostics
[`textDocument/references`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_references
[`textDocument/rename`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_rename
[`textDocument/signatureHelp`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_signatureHelp
[`textDocument/documentSymbols`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#textDocument_documentSymbols
[`workspace/didChangeWatchedFiles`]: https://github.com/Microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-14.md#workspace_didChangeWatchedFiles
[#31080]: https://github.com/golang/go/issues/31080
[#31553]: https://github.com/golang/go/issues/31553
[#31526]: https://github.com/golang/go/issues/31526
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/editor/emacs.md
---
title: "Gopls: Using Emacs"
---
## Installing `gopls`
To use `gopls` with Emacs, you must first
[install the `gopls` executable](../index.md#installation) and ensure that the directory
containing the resulting binary (either `$(go env GOBIN)` or `$(go env
GOPATH)/bin`) is in your `PATH`.
## Choosing an Emacs LSP client
To use `gopls` with Emacs, you will need to choose and install an Emacs LSP
client package. Two popular client packages are [LSP Mode] and [Eglot].
LSP Mode takes a batteries-included approach, with many integrations enabled
“out of the box” and several additional behaviors provided by `lsp-mode` itself.
Eglot takes a minimally-intrusive approach, focusing on smooth integration with
other established packages. It provides a few of its own `eglot-` commands but
no additional keybindings by default.
Once you have selected which client you want to use, install it per the packages
instructions: see [Eglot 1-2-3](https://github.com/joaotavora/eglot#1-2-3) or
[LSP Mode Installation](https://emacs-lsp.github.io/lsp-mode/page/installation/).
## Common configuration
Both Eglot and LSP Mode can integrate with popular packages in the Emacs
ecosystem:
* The built-in [`xref`] package provides cross-references.
* The built-in [Flymake] package provides an on-the-fly diagnostic overlay.
* [Company] mode displays code completion candidates (with a richer UI than
the built-in [`completion-at-point`]).
Eglot provides documentation using the built-in [ElDoc] minor mode, while LSP
Mode by default provides documentation using its own [`lsp-ui`] mode.
Eglot by default locates the project root using the [`project`] package. In LSP
Mode, this behavior can be configured using the `lsp-auto-guess-root` setting.
## Configuring LSP Mode
### Loading LSP Mode in `.emacs`
```elisp
(require 'lsp-mode)
(add-hook 'go-mode-hook #'lsp-deferred)
;; Set up before-save hooks to format buffer and add/delete imports.
;; Make sure you don't have other gofmt/goimports hooks enabled.
(defun lsp-go-install-save-hooks ()
(add-hook 'before-save-hook #'lsp-format-buffer t t)
(add-hook 'before-save-hook #'lsp-organize-imports t t))
(add-hook 'go-mode-hook #'lsp-go-install-save-hooks)
```
### Configuring `gopls` via LSP Mode
See [settings](../settings) for information about available gopls settings.
Stable gopls settings have corresponding configuration variables in `lsp-mode`.
For example, `(setq lsp-gopls-use-placeholders nil)` will disable placeholders
in completion snippets. See [`lsp-go`] for a list of available variables.
Experimental settings can be configured via `lsp-register-custom-settings`:
```lisp
(lsp-register-custom-settings
'(("gopls.completeUnimported" t t)
("gopls.staticcheck" t t)))
```
Note that after changing settings you must restart gopls using e.g. `M-x
lsp-restart-workspace`.
## Configuring Eglot
### Configuring `project` for Go modules in `.emacs`
Eglot uses the built-in `project` package to identify the LSP workspace for a
newly-opened buffer. The `project` package does not natively know about `GOPATH`
or Go modules. Fortunately, you can give it a custom hook to tell it to look for
the nearest parent `go.mod` file (that is, the root of the Go module) as the
project root.
```elisp
(require 'project)
(defun project-find-go-module (dir)
(when-let ((root (locate-dominating-file dir "go.mod")))
(cons 'go-module root)))
(cl-defmethod project-root ((project (head go-module)))
(cdr project))
(add-hook 'project-find-functions #'project-find-go-module)
```
### Loading Eglot in `.emacs`
```elisp
;; Optional: load other packages before eglot to enable eglot integrations.
(require 'company)
(require 'yasnippet)
(require 'go-mode)
(require 'eglot)
(add-hook 'go-mode-hook 'eglot-ensure)
;; Optional: install eglot-format-buffer as a save hook.
;; The depth of -10 places this before eglot's willSave notification,
;; so that notification reports the actual contents that will be saved.
(defun eglot-format-buffer-before-save ()
(add-hook 'before-save-hook #'eglot-format-buffer -10 t))
(add-hook 'go-mode-hook #'eglot-format-buffer-before-save)
```
Use `M-x eglot-upgrade-eglot` to upgrade to the latest version of
Eglot.
### Configuring `gopls` via Eglot
See [settings](../settings) for information about available gopls settings.
LSP server settings are controlled by the `eglot-workspace-configuration`
variable, which can be set either globally in `.emacs` or in a `.dir-locals.el` file in the project root.
`.emacs`:
```elisp
(setq-default eglot-workspace-configuration
'((:gopls .
((staticcheck . t)
(matcher . "CaseSensitive")))))
```
`.dir-locals.el`:
```elisp
((nil (eglot-workspace-configuration . ((gopls . ((staticcheck . t)
(matcher . "CaseSensitive")))))))
```
### Organizing imports with Eglot
`gopls` provides the import-organizing functionality of `goimports` as an LSP
code action, which you can invoke as needed by running `M-x eglot-code-actions`
(or a key of your choice bound to the `eglot-code-actions` function) and
selecting `Organize Imports` at the prompt.
To automatically organize imports before saving, add a hook:
```elisp
(add-hook 'before-save-hook
(lambda ()
(call-interactively 'eglot-code-action-organize-imports))
nil t)
```
## Troubleshooting
Common errors:
* When prompted by Emacs for your project folder, if you are using modules you
must select the module's root folder (i.e. the directory with the "go.mod").
If you are using GOPATH, select your $GOPATH as your folder.
* Emacs must have your environment set properly (PATH, GOPATH, etc). You can
run `M-x getenv PATH ` to see if your PATH is set in Emacs. If
not, you can try starting Emacs from your terminal, using [this
package][exec-path-from-shell], or moving your shell config from `.bashrc`
into `.profile` and logging out and back in.
* Make sure only one LSP client mode is installed. (For example, if using
`lsp-mode`, ensure that you are not _also_ enabling `eglot`.)
* Look for errors in the `*lsp-log*` buffer or run `M-x eglot-events-buffer`.
* Ask for help in the `#emacs` channel on the [Gophers slack].
[LSP Mode]: https://emacs-lsp.github.io/lsp-mode/
[Eglot]: https://github.com/joaotavora/eglot/blob/master/README.md
[`xref`]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html
[Flymake]: https://www.gnu.org/software/emacs/manual/html_node/flymake/Using-Flymake.html#Using-Flymake
[Company]: https://company-mode.github.io/
[`completion-at-point`]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Completion-in-Buffers.html
[ElDoc]: https://elpa.gnu.org/packages/eldoc.html
[`lsp-ui`]: https://emacs-lsp.github.io/lsp-ui/
[`lsp-go`]: https://github.com/emacs-lsp/lsp-mode/blob/master/clients/lsp-go.el
[`use-package`]: https://github.com/jwiegley/use-package
[`exec-path-from-shell`]: https://github.com/purcell/exec-path-from-shell
[settings]: settings.md
[Gophers slack]: https://invite.slack.golangbridge.org/
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/editor/helix.md
---
title: "Gopls: Using Helix"
---
Configuring `gopls` to work with Helix is rather straightforward. Install `gopls`, and then add it to the `PATH` variable. If it is in the `PATH` variable, Helix will be able to detect it automatically.
The documentation explaining how to install the default language servers for Helix can be found [here](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers)
## Installing `gopls`
The first step is to install `gopls` on your machine.
You can follow installation instructions [here](https://github.com/golang/tools/tree/master/gopls#installation).
## Setting your path to include `gopls`
Set your `PATH` environment variable to point to `gopls`.
If you used `go install` to download `gopls`, it should be in `$GOPATH/bin`.
If you don't have `GOPATH` set, you can use `go env GOPATH` to find it.
## Additional information
You can find more information about how to set up the LSP formatter [here](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers#autoformatting).
It is possible to use `hx --health go` to see that the language server is properly set up.
### Configuration
The settings for `gopls` can be configured in the `languages.toml` file.
The official Helix documentation for this can be found [here](https://docs.helix-editor.com/languages.html)
Configuration pertaining to `gopls` should be in the table `language-server.gopls`.
#### How to set flags
To set flags, add them to the `args` array in the `language-server.gopls` section of the `languages.toml` file.
#### How to set LSP configuration
Configuration options can be set in the `language-server.gopls.config` section of the `languages.toml` file, or in the `config` key of the `language-server.gopls` section of the `languages.toml` file.
#### A minimal config example
In the `~/.config/helix/languages.toml` file, the following snippet would set up `gopls` with a logfile located at `/tmp/gopls.log` and enable staticcheck.
```toml
[language-server.gopls]
command = "gopls"
args = ["-logfile=/tmp/gopls.log", "serve"]
[language-server.gopls.config]
"ui.diagnostic.staticcheck" = true
```
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/editor/sublime.md
---
title: "Gopls: Using Sublime Text"
---
Use the [LSP] package. After installing it using Package Control, do the following:
* Open the **Command Palette**
* Find and run the command **LSP: Enable Language Server Globally**
* Select the **gopls** item. Be careful not to select the similarly named *golsp* by mistake.
Finally, you should familiarise yourself with the LSP package's *Settings* and *Key Bindings*. Find them under the menu item **Preferences > Package Settings > LSP**.
## Examples
Minimal global LSP settings, that assume **gopls** and **go** appear on the PATH seen by Sublime Text:
```
{
"clients": {
"gopls": {
"enabled": true,
}
}
}
```
Global LSP settings that supply a specific PATH for finding **gopls** and **go**, as well as some settings for Sublime LSP itself:
```
{
"clients": {
"gopls": {
"enabled": true,
"env": {
"PATH": "/path/to/your/go/bin",
}
}
},
// Recommended by https://agniva.me/gopls/2021/01/02/setting-up-gopls-sublime.html
// except log_stderr mentioned there is no longer recognized.
"show_references_in_quick_panel": true,
"log_debug": true,
// These two are recommended by LSP-json as replacement for deprecated only_show_lsp_completions
"inhibit_snippet_completions": true,
"inhibit_word_completions": true,
}
```
LSP and gopls settings can also be adjusted on a per-project basis to override global settings.
```
{
"folders": [
{
"path": "/path/to/a/folder/one"
},
{
// If you happen to be working on Go itself, this can be helpful; go-dev/bin should be on PATH.
"path": "/path/to/your/go-dev/src/cmd"
}
],
"settings": {
"LSP": {
"gopls": {
// To use a specific version of gopls with Sublime Text LSP (e.g., to try new features in development)
"command": [
"/path/to/your/go/bin/gopls"
],
"env": {
"PATH": "/path/to/your/go-dev/bin:/path/to/your/go/bin",
"GOPATH": "",
},
"settings": {
"experimentalWorkspaceModule": true
}
}
},
// This will apply for all languages in this project that have
// LSP servers, not just Go, however cannot enable just for Go.
"lsp_format_on_save": true,
}
}
```
Usually changes to these settings are recognized after saving the project file, but it may sometimes be necessary to either restart the server(s) (**Tools > LSP > Restart Servers**) or quit and restart Sublime Text itself.
[LSP]: https://packagecontrol.io/packages/LSP
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/editor/vim.md
---
title: "Gopls: Using Vim or Neovim"
---
* [vim-go](#vimgo)
* [LanguageClient-neovim](#lcneovim)
* [Ale](#ale)
* [vim-lsp](#vimlsp)
* [vim-lsc](#vimlsc)
* [coc.nvim](#cocnvim)
* [govim](#govim)
* [Neovim v0.5.0+](#neovim)
* [Installation](#neovim-install)
* [Custom Configuration](#neovim-config)
* [Imports](#neovim-imports)
* [Omnifunc](#neovim-omnifunc)
* [Additional Links](#neovim-links)
## vim-go
Use [vim-go] ver 1.20+, with the following configuration:
```vim
let g:go_def_mode='gopls'
let g:go_info_mode='gopls'
```
## LanguageClient-neovim
Use [LanguageClient-neovim], with the following configuration:
```vim
" Launch gopls when Go files are in use
let g:LanguageClient_serverCommands = {
\ 'go': ['gopls']
\ }
" Run gofmt on save
autocmd BufWritePre *.go :call LanguageClient#textDocument_formatting_sync()
```
## Ale
Use [ale]:
```vim
let g:ale_linters = {
\ 'go': ['gopls'],
\}
```
see [this issue][ale-issue-2179]
## vim-lsp
Use [prabirshrestha/vim-lsp], with the following configuration:
```vim
augroup LspGo
au!
autocmd User lsp_setup call lsp#register_server({
\ 'name': 'gopls',
\ 'cmd': {server_info->['gopls']},
\ 'whitelist': ['go'],
\ })
autocmd FileType go setlocal omnifunc=lsp#complete
"autocmd FileType go nmap gd (lsp-definition)
"autocmd FileType go nmap ,n (lsp-next-error)
"autocmd FileType go nmap ,p (lsp-previous-error)
augroup END
```
## vim-lsc
Use [natebosch/vim-lsc], with the following configuration:
```vim
let g:lsc_server_commands = {
\ "go": {
\ "command": "gopls serve",
\ "log_level": -1,
\ "suppress_stderr": v:true,
\ },
\}
```
The `log_level` and `suppress_stderr` parts are needed to prevent breakage from logging. See
issues [#180](https://github.com/natebosch/vim-lsc/issues/180) and
[#213](https://github.com/natebosch/vim-lsc/issues/213).
## coc.nvim
Use [coc.nvim], with the following `coc-settings.json` configuration:
```json
"languageserver": {
"go": {
"command": "gopls",
"rootPatterns": ["go.work", "go.mod", ".vim/", ".git/", ".hg/"],
"filetypes": ["go"],
"initializationOptions": {
"usePlaceholders": true
}
}
}
```
If you use `go.work` files, you may want to set the
`workspace.workspaceFolderCheckCwd` option. This will force coc.nvim to search
parent directories for `go.work` files, even if the current open directory has
a `go.mod` file. See the
[coc.nvim documentation](https://github.com/neoclide/coc.nvim/wiki/Using-workspaceFolders)
for more details.
Other [settings](../settings) can be added in `initializationOptions` too.
The `editor.action.organizeImport` code action will auto-format code and add missing imports. To run this automatically on save, add the following line to your `init.vim`:
```vim
autocmd BufWritePre *.go :call CocAction('runCommand', 'editor.action.organizeImport')
```
## govim
In vim classic only, use the experimental [`govim`], simply follow the [install steps][govim-install].
## Neovim v0.5.0+
To use the new native LSP client in Neovim, make sure you
[install][nvim-install] Neovim v.0.5.0+,
the `nvim-lspconfig` configuration helper plugin, and check the
[`gopls` configuration section][nvim-lspconfig] there.
### Installation
You can use Neovim's native plugin system. On a Unix system, you can do that by
cloning the `nvim-lspconfig` repository into the correct directory:
```sh
dir="${HOME}/.local/share/nvim/site/pack/nvim-lspconfig/opt/nvim-lspconfig/"
mkdir -p "$dir"
cd "$dir"
git clone 'https://github.com/neovim/nvim-lspconfig.git' .
```
### Configuration
nvim-lspconfig aims to provide reasonable defaults, so your setup can be very
brief.
```lua
local lspconfig = require("lspconfig")
lspconfig.gopls.setup({})
```
However, you can also configure `gopls` for your preferences. Here's an
example that enables `unusedparams`, `staticcheck`, and `gofumpt`.
```lua
local lspconfig = require("lspconfig")
lspconfig.gopls.setup({
settings = {
gopls = {
analyses = {
unusedparams = true,
},
staticcheck = true,
gofumpt = true,
},
},
})
```
### Imports and Formatting
Use the following configuration to have your imports organized on save using
the logic of `goimports` and your code formatted.
```lua
autocmd("BufWritePre", {
pattern = "*.go",
callback = function()
local params = vim.lsp.util.make_range_params()
params.context = {only = {"source.organizeImports"}}
-- buf_request_sync defaults to a 1000ms timeout. Depending on your
-- machine and codebase, you may want longer. Add an additional
-- argument after params if you find that you have to write the file
-- twice for changes to be saved.
-- E.g., vim.lsp.buf_request_sync(0, "textDocument/codeAction", params, 3000)
local result = vim.lsp.buf_request_sync(0, "textDocument/codeAction", params)
for cid, res in pairs(result or {}) do
for _, r in pairs(res.result or {}) do
if r.edit then
local enc = (vim.lsp.get_client_by_id(cid) or {}).offset_encoding or "utf-16"
vim.lsp.util.apply_workspace_edit(r.edit, enc)
end
end
end
vim.lsp.buf.format({async = false})
end
})
```
### Omnifunc
In Neovim v0.8.1 and later if you don't set the option `omnifunc`, it will auto
set to `v:lua.vim.lsp.omnifunc`. If you are using an earlier version, you can
configure it manually:
```lua
local on_attach = function(client, bufnr)
-- Enable completion triggered by
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
end
require('lspconfig').gopls.setup({
on_attach = on_attach
})
```
### Additional Links
* [Neovim's official LSP documentation][nvim-docs].
[vim-go]: https://github.com/fatih/vim-go
[LanguageClient-neovim]: https://github.com/autozimu/LanguageClient-neovim
[ale]: https://github.com/w0rp/ale
[ale-issue-2179]: https://github.com/w0rp/ale/issues/2179
[prabirshrestha/vim-lsp]: https://github.com/prabirshrestha/vim-lsp/
[natebosch/vim-lsc]: https://github.com/natebosch/vim-lsc/
[natebosch/vim-lsc#180]: https://github.com/natebosch/vim-lsc/issues/180
[coc.nvim]: https://github.com/neoclide/coc.nvim/
[`govim`]: https://github.com/myitcv/govim
[govim-install]: https://github.com/myitcv/govim/blob/master/README.md#govim---go-development-plugin-for-vim8
[nvim-docs]: https://neovim.io/doc/user/lsp.html
[nvim-install]: https://github.com/neovim/neovim/wiki/Installing-Neovim
[nvim-lspconfig]: https://github.com/neovim/nvim-lspconfig/blob/master/doc/configs.md#gopls
[nvim-lspconfig-imports]: https://github.com/neovim/nvim-lspconfig/issues/115
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/editor/zed.md
---
title: "Gopls: Using Zed"
---
## Install `gopls`
To use `gopls` with [Zed](https://zed.dev/), first
[install the `gopls` executable](../index.md#installation) and ensure that the directory
containing the resulting binary (either `$(go env GOBIN)` or `$(go env
GOPATH)/bin`) is in your `PATH`.
## That's it
Zed has a built-in LSP client and knows to run `gopls` when visiting a
Go source file, so most features work right out of the box.
Zed does not yet support external `window/showDocument` requests,
so web-based features will not work;
see [Zed issue 24852](https://github.com/zed-industries/zed/discussions/24852).
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/assembly.md
---
title: "Gopls: Support for Go *.s assembly files"
---
Gopls has rudimentary support for LSP operations in Go assembly files.
Go assembly files have a `.s` file name extension. LSP clients need to
be configured to recognize `.s` files as Go assembly files, since this
file name extension is also used for assembly files in other
languages. A good heuristic is that if a file named `*.s` belongs to a
directory containing at least one `*.go` file, then the `.s` file is
Go assembly, and its appropriate language server is gopls.
Only Definition (`textDocument/definition`) requests are currently
supported. For example, a Definition request on the `sigpanic`
symbol in this file in GOROOT/src/runtime/asm.s:
```asm
JMP ·sigpanic(SB)
```
returns the location of the function declaration in
GOROOT/src/runtime/signal_unix.go:
```go
//go:linkname sigpanic
func sigpanic() {
```
See also issue https://go.dev/issue/71754, which tracks the development of LSP
features in Go assembly files.
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/completion.md
---
title: "Gopls: Completion"
---
TODO(https://go.dev/issue/62022): document
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/diagnostics.md
---
title: "Gopls: Diagnostics"
---
Gopls continuously annotates all your open files of source code with a
variety of diagnostics. Every time you edit a file or make a
configuration change, gopls asynchronously recomputes these
diagnostics and sends them to the client using the LSP
[`publishDiagnostics`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_publishDiagnostics)
notification, giving you real-time feedback that reduces the cost of
common mistakes.
Diagnostics come from two main sources: compilation errors and analysis findings.
- **Compilation errors** are those that you would obtain from running `go
build`. Gopls doesn't actually run the compiler; that would be too
slow. Instead it runs `go list` (when needed) to compute the
metadata of the compilation, then processes those packages in a similar
manner to the compiler front-end: reading, scanning, and parsing the
source files, then type-checking them. Each of these steps can
produce errors that gopls will surface as a diagnostic.
The `source` field of the LSP `Diagnostic` record indicates where
the diagnostic came from: those with source `"go list"` come from
the `go list` command, and those with source `"compiler"` come from
gopls' parsing or type checking phases, which are similar to those
used in the Go compiler.

The example above shows a `string + int` addition, causes the type
checker to report a `MismatchedTypes` error. The diagnostic contains
a link to the documentation about this class of type error.
- **Analysis findings** come from the [**Go analysis
framework**](https://golang.org/x/tools/go/analysis), the system
used by `go vet` to apply a variety of additional static checks to
your Go code. The best-known example is the [`printf`
analyzer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/printf),
which reports calls to [`fmt.Printf`](https://pkg.go.dev/fmt#Printf)
where the format "verb" doesn't match the argument, such as
`fmt.Printf("%d", "three")`.
Gopls provides dozens of analyzers aggregated from a variety of
suites; see [Analyzers](../analyzers.md) for the complete list. The
`source` field of each diagnostic produced by an analyzer records
the name of the analyzer that produced it.

The example above shows a `printf` formatting mistake. The diagnostic contains
a link to the documentation for the `printf` analyzer.
There is an optional third source of diagnostics:
- **Compiler optimization details** are diagnostics that report
details relevant to optimization decisions made by the Go
compiler, such as whether a variable escapes or a slice index
requires a bounds check.
Optimization decisions include:
whether a variable escapes, and how escape is inferred;
whether a nil-pointer check is implied or eliminated; and
whether a function can be inlined.
This source is disabled by default but can be enabled on a
package-by-package basis by invoking the
`source.toggleCompilerOptDetails` ("{Show,Hide} compiler optimization
details") code action.
Remember that the compiler's optimizer runs only on packages that
are transitively free from errors, so optimization diagnostics
will not be shown on packages that do not build.
## Recomputation of diagnostics
By default, diagnostics are automatically recomputed each time the source files
are edited.
Compilation errors in open files are updated after a very short delay
(tens of milliseconds) after each file change, potentially after every keystroke.
This ensures rapid feedback of syntax and type errors while editing.
Compilation and analysis diagnostics for the whole workspace are much
more expensive to compute, so they are usually recomputed after a
short idle period (around 1s) following an edit.
The [`diagnosticsDelay`](../settings.md#diagnosticsDelay) setting determines
this period.
Alternatively, diagnostics may be triggered only after an edited file
is saved, using the
[`diagnosticsTrigger`](../settings.md#diagnosticsTrigger) setting.
When initialized with `"pullDiagnostics": true`, gopls also supports
["pull diagnostics"](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics),
an alternative mechanism for recomputing diagnostics in which the client
requests diagnostics from gopls explicitly using the `textDocument/diagnostic`
request. This feature is off by default until the performance of pull
diagnostics is comparable to push diagnostics.
## Quick fixes
Each analyzer diagnostic may suggest one or more alternative
ways to fix the problem by editing the code.
For example, when a `return` statement has too few operands,
the [`fillreturns`](../analyzers.md#fillreturns) analyzer
suggests a fix that heuristically fills in the missing ones
with suitable values. Applying the fix eliminates the compilation error.

The screenshot above shows VS Code's Quick Fix menu for an "unused
parameter" analysis diagnostic with two alternative fixes.
(See [Remove unused parameter](transformation.md#remove-unused-parameter) for more detail.)
Suggested fixes that are indisputably safe are [code
actions](transformation.md#code-actions) whose kind is
`"source.fixAll"`.
Many client editors have a shortcut to apply all such fixes.
TODO(adonovan): audit all the analyzers to ensure that their
documentation is up-to-date w.r.t. any fixes they suggest.
Settings:
- The [`diagnosticsDelay`](../settings.md#diagnosticsDelay) setting determines
the idle period after an edit before diagnostics are recomputed.
- The [`diagnosticsTriggerr`](../settings.md#diagnosticsTrigger) setting determines
what events cause recomputation of diagnostics.
- The [`linkTarget`](../settings.md#linkTarget) setting specifies
the base URI for Go package links in the Diagnostic.CodeDescription field.
Client support:
- **VS Code**: Each diagnostic appears as a squiggly underline.
Hovering reveals the details, along with any suggested fixes.
- **Emacs + eglot**: Each diagnostic appears as a squiggly underline.
Hovering reveals the details. Use `M-x eglot-code-action-quickfix`
to apply available fixes; it will prompt if there are more than one.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls check file.go`
### `stubMissingInterfaceMethods`: Declare missing methods of I
When a value of a concrete type is assigned to a variable of an
interface type, but the concrete type does not possess all the
necessary methods, the type checker will report a "missing method"
error.
In this situation, gopls offers a quick fix to add stub declarations
of all the missing methods to the concrete type so that it implements
the interface.
For example, this function will not compile because the value
`NegativeErr{}` does not implement the "error" interface:
```go
func sqrt(x float64) (float64, error) {
if x < 0 {
return 0, NegativeErr{} // error: missing method
}
...
}
type NegativeErr struct{}
```
Gopls will offer a quick fix to declare this method:
```go
// Error implements [error.Error].
func (NegativeErr) Error() string {
panic("unimplemented")
}
```
Beware that the new declarations appear alongside the concrete type,
which may be in a different file or even package from the cursor
position.
(Perhaps gopls should send a `showDocument` request to navigate the
client there, or a progress notification indicating that something
happened.)
### `StubMissingCalledFunction`: Declare missing method T.f
When you attempt to call a method on a type that does not have that method,
the compiler will report an error such as "type X has no field or method Y".
In this scenario, gopls now offers a quick fix to generate a stub declaration of
the missing method, inferring its type from the call.
Consider the following code where `Foo` does not have a method `bar`:
```go
type Foo struct{}
func main() {
var s string
f := Foo{}
s = f.bar("str", 42) // error: f.bar undefined (type Foo has no field or method bar)
}
```
Gopls will offer a quick fix, "Declare missing method Foo.bar".
When invoked, it creates the following declaration:
```go
func (f Foo) bar(s string, i int) string {
panic("unimplemented")
}
```
### `CreateUndeclared`: Create missing declaration for "undeclared name: X"
A Go compiler error "undeclared name: X" indicates that a variable or function is being used before
it has been declared in the current scope. In this scenario, gopls offers a quick fix to create the declaration.
#### Declare a new variable
When you reference a variable that hasn't been declared:
```go
func main() {
x := 42
min(x, y) // error: undefined: y
}
```
The quick fix would insert a declaration with a default
value inferring its type from the context:
```go
func main() {
x := 42
y := 0
min(x, y)
}
```
#### Declare a new function
Similarly, if you call a function that hasn't been declared:
```go
func main() {
var s string
s = doSomething(42) // error: undefined: doSomething
}
```
Gopls will insert a new function declaration below,
inferring its type from the call:
```go
func main() {
var s string
s = doSomething(42)
}
func doSomething(i int) string {
panic("unimplemented")
}
```
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/index.md
---
title: "Gopls: Index of features"
---
This page provides an index of all supported features of gopls that
are accessible through the [language server protocol](https://microsoft.github.io/language-server-protocol/) (LSP).
It is intended for:
- **users of gopls** learning its capabilities so that they get the most out of their editor;
- **editor maintainers** adding or improving Go support in an LSP-capable editor; and
- **contributors to gopls** trying to understand how it works.
In an ideal world, Go users would not need to know that gopls or even
LSP exists, as their LSP-enabled editors would implement every facet
of the protocol and expose each feature in a natural and discoverable
way. In reality, editors vary widely in their support for LSP, so
unfortunately these documents necessarily involve many details of the
protocol.
We also list [settings](../settings.md) that affect each feature.
Most features are illustrated with reference to VS Code, but we will
briefly mention whether each feature is supported in other popular
clients, and if so, how to find it. We welcome contributions, edits,
and updates from users of any editor.
Contributors should [update this documentation](../contributing.md#documentation)
when making significant changes to existing features or when adding new ones.
- [Passive](passive.md): features that are always on and require no special action
- [Hover](passive.md#hover): information about the symbol under the cursor
- [Signature Help](passive.md#signature-help): type information about the enclosing function call
- [Document Highlight](passive.md#document-highlight): highlight identifiers referring to the same symbol
- [Inlay Hint](passive.md#inlay-hint): show implicit names of struct fields and parameter names
- [Semantic Tokens](passive.md#semantic-tokens): report syntax information used by editors to color the text
- [Folding Range](passive.md#folding-range): report text regions that can be "folded" (expanded/collapsed) in an editor
- [Document Link](passive.md#document-link): extracts URLs from doc comments, strings in current file so client can linkify
- [Diagnostics](diagnostics.md): compile errors and static analysis findings
- [Navigation](navigation.md): navigation of cross-references, types, and symbols
- [Definition](navigation.md#definition): go to definition of selected symbol
- [Type Definition](navigation.md#type-definition): go to definition of type of selected symbol
- [References](navigation.md#references): list references to selected symbol
- [Implementation](navigation.md#implementation): show "implements" relationships of selected type
- [Document Symbol](navigation.md#document-symbol): outline of symbols defined in current file
- [Symbol](navigation.md#symbol): fuzzy search for symbol by name
- [Selection Range](navigation.md#selection-range): select enclosing unit of syntax
- [Call Hierarchy](navigation.md#call-hierarchy): show outgoing/incoming calls to the current function
- [Type Hierarchy](navigation.md#type-hierarchy): show interfaces/implementations of the current type
- [Completion](completion.md): context-aware completion of identifiers, statements
- [Code transformation](transformation.md): fixes and refactorings
- [Formatting](transformation.md#formatting): format the source code
- [Rename](transformation.md#rename): rename a symbol or package
- [Organize imports](transformation.md#source.organizeImports): organize the import declaration
- [Extract](transformation.md#refactor.extract): extract selection to a new file/function/variable
- [Inline](transformation.md#refactor.inline.call): inline a call to a function or method
- [Miscellaneous rewrites](transformation.md#refactor.rewrite): various Go-specific refactorings
- [Add test for func](transformation.md#source.addTest): create a test for the selected function
- [Web-based queries](web.md): commands that open a browser page
- [Package documentation](web.md#doc): browse documentation for current Go package
- [Free symbols](web.md#freesymbols): show symbols used by a selected block of code
- [Assembly](web.md#assembly): show listing of assembly code for selected function
- [Split package](web.md#splitpkg): split a package into two or more components
- Support for non-Go files:
- [Template files](templates.md): files parsed by `text/template` and `html/template`
- [go.mod and go.work files](modfiles.md): Go module and workspace manifests
- [Go *.s assembly files](assembly.md): Go assembly files
- [Command-line interface](../command-line.md): CLI for debugging and scripting (unstable)
- [Model Context Protocol (MCP)](mcp.md): use some features in AI-assisted environments
You can find this page from within your editor by executing the
`gopls.doc.features` [code action](transformation.md#code-actions),
which opens it in a web browser.
In VS Code, you can find it on the "Quick fix" menu.
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/mcp.md
---
title: "Gopls: Model Context Protocol support"
---
Gopls includes an experimental built-in server for the [Model Context
Protocol](https://modelcontextprotocol.io/introduction) (MCP), allowing it to
expose a subset of its functionality to AI assistants in the form of MCP tools.
## Running the MCP server
There are two modes for running this server: 'attached' and 'detached'. In
attached mode, the MCP server operates in the context of an active gopls LSP
session, and so is able to share memory with your LSP session and observe the
current unsaved buffer state. In detached mode, gopls interacts with a headless
LSP session, and therefore only sees saved files on disk.
### Attached mode
To use the 'attached' mode, run gopls with the `-mcp.listen` flag. For
example:
```
gopls serve -mcp.listen=localhost:8092
```
This exposes an HTTP based MCP server using the server-sent event transport
(SSE), available at `http://localhost:8092/sessions/1` (assuming you have only
one [session](../daemon.md) on your gopls instance).
### Detached mode
To use the 'detached' mode, run the `mcp` subcommand:
```
gopls mcp
```
This runs a standalone gopls instance that speaks MCP over stdin/stdout.
## Instructions to the model
This gopls MCP server includes model instructions for its usage, describing
workflows for interacting with Go code using its available tools. These
instructions are automatically published during the MCP server initialization,
but you may want to also load them as additional context in your AI-assisted
session, to emphasize their importance. The `-instructions` flag causes them to
be printed, so that you can do, for example:
```
gopls mcp -instructions > /path/to/contextFile.md
```
## Security considerations
The gopls MCP server is a wrapper around the functionality ordinarily exposed
by gopls through the Language Server Protocol (LSP). As such, gopls' tools
may perform any of the operations gopls normally performs, including:
- reading files from the file system, and returning their contents in tool
results (such as when providing context);
- executing the `go` command to load package information, which may result in
calls to https://proxy.golang.org to download Go modules, and writes to go
caches;
- writing to gopls' cache or persistant configuration files; and
- uploading weekly telemetry data **if you have opted in** to [Go telemetry](https://go.dev/doc/telemetry).
The gopls MCP server does not perform any operations not already performed by
gopls in an ordinary IDE session. Like most LSP servers, gopls does not
generally write directly to your source tree, though it may instruct the client
to apply edits. Nor does it make arbitrary requests over the network, though it
may make narrowly scoped requests to certain services such as the Go module
mirror or the Go vulnerability database, which can't readily be exploited as a
vehicle for exfiltration by a confused agent. Nevertheless, these capabilities
may require additional consideration when used as part of an AI-enabled system.
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/modfiles.md
---
title: "Gopls: Support for go.mod and go.work files"
---
TODO: document these features for go.{mod,work} files:
- hover
- vulncheck
- add dependency
- update dependency
- diagnostics
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/navigation.md
---
title: "Gopls: Navigation features"
---
This page documents gopls features for navigating your source code.
## Definition
The LSP [`textDocument/definition`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_definition)
request returns the location of the declaration of the symbol under the cursor.
Most editors provide a command to navigate directly to that location.
A definition query also works in these unexpected places:
- On an **import path**, it returns the list of locations, of
each package declaration in the files of the imported package.
- On a **package declaration**, it returns the location of
the package declaration that provides the documentation of that package.
- On a symbol in a **[`go:linkname` directive](https://pkg.go.dev/cmd/compile)**,
it returns the location of that symbol's declaration.
- On a **[doc link](https://tip.golang.org/doc/comment#doclinks)**, it returns
(like [`hover`](passive.md#hover)) the location of the linked symbol.
- On a file name in a **[`go:embed` directive](https://pkg.go.dev/embed)**,
it returns the location of the embedded file.
- On the declaration of a non-Go function (a `func` with no body),
it returns the location of the assembly implementation, if any,
- On a **return statement**, it returns the location of the function's result variables.
- On a **goto**, **break**, or **continue** statement, it returns the
location of the label, the closing brace of the relevant block statement, or the
start of the relevant loop, respectively.
Client support:
- **VS Code**: Use [Go to Definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition) (`F12` or `⌘`-click).
If the cursor is already at the declaration, the request is instead interpreted as "Go to References".
- **Emacs + eglot**: use [`M-x xref-find-definitions`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html).
- **Vim + coc.nvim**: ??
- **CLI**: `gopls definition file.go:#offset`
## References
The LSP [`textDocument/references`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_references)
request returns the locations of all identifiers that refer to the symbol under the cursor.
The references algorithm handles various parts of syntax as follows:
- The references to a **symbol** report all uses of that symbol.
In the case of exported symbols this may include locations in other packages.
- The references to a **package declaration** are all the
direct imports of the package, along with all the other package
declarations in the same package.
- It is an error to request the references to a **built-in symbol**
such as `int` or `append`,
as they are presumed too numerous to be of interest.
- The references to an **interface method** include references to
concrete types that implement the interface. Similarly, the
references to a **method of a concrete type** include references to
corresponding interface methods.
- An **embedded field** `T` in a struct type such as `struct{T}` is
unique in Go in that it is both a reference (to a type) and a
definition (of a field).
The `references` operation reports only the references to it [as a field](https://go.dev/issue/63521).
To find references to the type, jump to the type declararation first.
- The references to a module in a **require** directive in a **go.mod** file are
the **import** statements in packages of the main module (defined by the go.mod file) that
import packages of the required module.
Be aware that a references query returns information only about the
build configuration used to analyze the selected file, so if you ask
for the references to a symbol defined in `foo_windows.go`, the result
will never include the file `bar_linux.go`, even if that file refers
to a symbol of the same name; see https://go.dev/issue/65755.
Clients can request that the declaration be included among the
references; most do.
Client support:
- **VS Code**: Use [`Go to References`](https://code.visualstudio.com/docs/editor/editingevolved#_peek) to quickly "peek" at the references,
or `Find all References` to open the references panel.
- **Emacs + eglot**: Via [`xref` package](https://www.gnu.org/software/emacs/manual/html_node/emacs/Xref.html): use `M-x xref-find-references`.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls references file.go:#offset`
## Implementation
The LSP
[`textDocument/implementation`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_implementation)
request queries the relation between abstract and concrete types and
their methods.
Interfaces and concrete types are matched using method sets:
- When invoked on a reference to an **interface type**, it returns the
location of the declaration of each type that implements
the interface.
- When invoked on a **concrete type**,
it returns the locations of the matching interface types.
- When invoked on an **interface method**, it returns the corresponding
methods of the types that satisfy the interface.
- When invoked on a **concrete method**,
it returns the locations of the matching interface methods.
For example:
- `implementation(io.Reader)` includes subinterfaces such as `io.ReadCloser`,
and concrete implementations such as `*os.File`. It also includes
other declarations equivalent to `io.Reader`.
- `implementation(os.File)` includes only interfaces, such as
`io.Reader` and `io.ReadCloser`.
The LSP's Implementation feature has a built-in bias towards subtypes,
possibly because in languages such as Java and C++ the relationship
between a type and its supertypes is explicit in the syntax, so the
corresponding "Go to interfaces" operation can be achieved as sequence
of two or more "Go to definition" steps: the first to visit the type
declaration, and the rest to sequentially visit ancestors.
(See https://github.com/microsoft/language-server-protocol/issues/2037.)
In Go, where there is no syntactic relationship between two types, a
search is required when navigating in either direction between
subtypes and supertypes. The heuristic above works well in many cases,
but it is not possible to ask for the superinterfaces of
`io.ReadCloser`. For more explicit navigation between subtypes and
supertypes, use the [Type Hierarchy](#Type Hierarchy) feature.
Only non-trivial interfaces are considered; no implementations are
reported for type `any`.
Within the same package, all matching types/methods are reported.
However, across packages, only exported package-level types and their
methods are reported, so local types (whether interfaces, or struct
types with methods due to embedding) may be missing from the results.
Functions, `func` types, and dynamic function calls are matched using signatures:
- When invoked on the `func` token of a **function definition**,
it returns the locations of the matching signature types
and dynamic call expressions.
- When invoked on the `func` token of a **signature type**,
it returns the locations of the matching concrete function definitions.
- When invoked on the `(` token of a **dynamic function call**,
it returns the locations of the matching concrete function
definitions.
If either the target type or the candidate type are generic, the
results will include the candidate type if there is any instantiation
of the two types that would allow one to implement the other.
(Note: the matcher doesn't current implement full unification, so type
parameters are treated like wildcards that may match arbitrary
types, without regard to consistency of substitutions across the
method set or even within a single method.
This may lead to occasional spurious matches.)
Since a type may be both a function type and a named type with methods
(for example, `http.HandlerFunc`), it may participate in both kinds of
implementation queries (by method-sets and function signatures).
Queries using method-sets should be invoked on the type or method name,
and queries using signatures should be invoked on a `func` or `(` token.
Client support:
- **VS Code**: Use [Go to Implementations](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-implementation) (`⌘F12`).
- **Emacs + eglot**: Use `M-x eglot-find-implementation`.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls implementation file.go:#offset`
## Type Definition
The LSP
[`textDocument/typeDefinition`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_typeDefinition)
request returns the location of the type of the selected symbol.
For example, if the selection is the name `buf` of a local variable of
type `*bytes.Buffer`, a `typeDefinition` query will return the
location of the type `bytes.Buffer`.
Clients typically navigate to that location.
Type constructors such as pointer, array, slice, channel, and map are
stripped off the selected type in the search for a named type. For
example, if x is of type `chan []*T`, the reported type definition
will be that of `T`.
Similarly, if the symbol's type is a function with one "interesting"
(named, non-`error`) result type, the function's result type is used.
Gopls currently requires that a `typeDefinition` query be applied to a
symbol, not to an arbitrary expression; see https://go.dev/issue/67890 for
potential extensions of this functionality.
Client support:
- **VS Code**: Use [Go to Type Definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-implementation).
- **Emacs + eglot**: Use `M-x eglot-find-typeDefinition`.
- **Vim + coc.nvim**: ??
- **CLI**: not supported
## Document Symbol
The `textDocument/documentSymbol` LSP query reports the list of
top-level declarations in this file. Clients may use this information
to present an overview of the file, and an index for faster navigation.
Gopls responds with the
[`DocumentSymbol`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbol)
type if the client indicates
[`hierarchicalDocumentSymbolSupport`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#documentSymbolClientCapabilities);
otherwise it returns a
[`SymbolInformation`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#symbolInformation).
Client support:
- **VS Code**: Use the [Outline view](https://code.visualstudio.com/docs/getstarted/userinterface#_outline-view) for navigation.
- **Emacs + eglot**: Use [`M-x imenu`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Imenu.html#Imenu) to jump to a symbol.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls links file.go`
## Symbol
The
[`workspace/symbol`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#workspace_symbol)
LSP query searches an index of all the symbols in the workspace.
The default symbol matching algorithm (`fastFuzzy`), inspired by the
popular fuzzy matcher [FZF](https://github.com/junegunn/fzf), attempts
a variety of inexact matches to correct for misspellings or abbreviations in your
query. For example, it considers `DocSym` a match for `DocumentSymbol`.
Settings:
- The [`symbolMatcher`](../settings.md#symbolMatcher) setting controls the algorithm used for symbol matching.
- The [`symbolStyle`](../settings.md#symbolStyle) setting controls how symbols are qualified in symbol responses.
- The [`symbolScope`](../settings.md#symbolScope) setting determines the scope of the query.
- The [`directoryFilters`](../settings.md#directoryFilters) setting specifies directories to be excluded from the search.
Client support:
- **VS Code**: Use ⌘T to open [Go to Symbol](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-symbol) with workspace scope. (Alternatively, use Ctrl-Shift-O, and add a `@` prefix to search within the file or a `#` prefix to search throughout the workspace.)
- **Emacs + eglot**: Use [`M-x xref-find-apropos`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Looking-Up-Identifiers.html) to show symbols that match a search term.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls links file.go`
## Selection Range
The
[`textDocument/selectionRange`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_selectionRange)
LSP query returns information about the lexical extent of each piece
of syntax enclosing the current selection.
Clients may use it to provide an operation to expand the selection
to successively larger expressions.
Client support:
- **VSCode**: Use `⌘⇧^→` to expand the selection or `⌘⇧^←` to contract it again; watch this [video](https://www.youtube.com/watch?v=dO4SGAMl7uQ).
- **Emacs + eglot**: Not standard. Use `M-x eglot-expand-selection` defined in [this configuration snippet](https://github.com/joaotavora/eglot/discussions/1220#discussioncomment-9321061).
- **Vim + coc.nvim**: ??
- **CLI**: not supported
## Call Hierarchy
The LSP CallHierarchy mechanism consists of three queries that
together enable clients to present a hierarchical view of a portion of
the static call graph:
- [`textDocument/prepareCallHierarchy`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_prepareCallHierarchy) returns a list of [items](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchyItem) for a given position, each representing a named function or method enclosing the position;
- [`callHierarchyItem/incomingCalls`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchy_incomingCalls) returns the set of call sites that call the selected item; and
- [`callHierarchy/outgoingCalls`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#callHierarchy_incomingCalls) returns the set of functions called by the selected item.
Invoke the command while selecting the name in a function declaration.
Dynamic calls are not included, because it is not analytically
practical to detect them. So, beware that the results may not be
exhaustive, and perform a [References](#references) query if necessary.
The hierarchy does not consider a nested function distinct from its
enclosing named function. (Without the ability to detect dynamic
calls, it would make little sense do so.)
The screenshot below shows the outgoing call tree rooted at `f`. The
tree has been expanded to show a path from `f` to the `String` method
of `fmt.Stringer` through the guts of `fmt.Sprint:`
Client support:
- **VS Code**: `Show Call Hierarchy` menu item (`⌥⇧H`) opens [Call hierarchy view](https://code.visualstudio.com/docs/cpp/cpp-ide#_call-hierarchy) (note: docs refer to C++ but the idea is the same for Go).
- **Emacs + eglot**: Not standard; install with `(package-vc-install "https://github.com/dolmens/eglot-hierarchy")`. Use `M-x eglot-hierarchy-call-hierarchy` to show the direct incoming calls to the selected function; use a prefix argument (`C-u`) to show the direct outgoing calls. There is no way to expand the tree.
- **CLI**: `gopls call_hierarchy file.go:#offset` shows outgoing and incoming calls.
## Type Hierarchy
The LSP TypeHierarchy mechanism consists of three queries that
together enable clients to present a hierarchical view of a portion of
the subtyping relation over named types.
- [`textDocument/prepareTypeHierarchy`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#textDocument_prepareTypeHierarchy) returns an [item](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchyItem) describing the named type at the current position;
- [`typeHierarchyItem/subtypes`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchy_subtypes) returns the set of subtypes of the selected (interface) type; and
- [`typeHierarchy/supertypes`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification#typeHierarchy_supertypes) returns the set of supertypes (interface types) of the selected type.
Invoke the command while selecting the name of a type.
As with an Implementation query, a type hierarchy query reports
function-local types only within the same package as the query type.
Also the result does not include alias types, only defined types.
Caveats:
- The type hierarchy supports only named types and their assignability
relation. By contrast, the Implementations request also reports the
relation between unnamed `func` types and function declarations,
function literals, and dynamic calls of values of those types.
Client support:
- **VS Code**: `Show Type Hierarchy` menu item opens [Type hierarchy view](https://code.visualstudio.com/docs/java/java-editing#_type-hierarchy) (note: docs refer to Java but the idea is the same for Go).
- **Emacs + eglot**: Support added in March 2025. Use `M-x eglot-show-call-hierarchy`.
- **CLI**: not yet supported.
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/passive.md
---
title: "Gopls: Passive features"
---
This page documents the fundamental LSP features of gopls that may be
described as "passive", since many editors use them to continuously
provide information about your source files without requiring any
special action.
See also [Code Lenses](../codelenses.md), some of which annotate your
source code with additional information and may thus also be
considered passive features.
## Hover
The LSP [`textDocument/hover`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_hover)
query returns a description of the code currently under the cursor, such
as its name, kind, type, value (for a constant), abbreviated
declaration (for a type), doc comment (if any), and a link to the
symbol's documentation on `pkg.go.dev`. The client may request either
plain text or Markdown.
Depending on the selection, the response may include additional information.
For example, hovering over a type shows its declared methods,
plus any methods promoted from embedded fields.
**Doc links**: A doc comment may refer to another symbol using square
brackets, for example `[fmt.Printf]`. Hovering over one of these
[doc links](https://go.dev/doc/comment#doclinks) reveals
information about the referenced symbol.
**Struct size/offset info**: for declarations of struct types,
hovering over the name reveals the struct's size in bytes:
And hovering over each field name shows the size and offset of that field:
This information may be useful when optimizing the layout of your data
structures, or when reading assembly files or stack traces that refer
to each field by its cryptic byte offset.
In addition, Hover reports:
- the struct's size class, which is the number of bytes actually
allocated by the Go runtime for a single object of this type; and
- the percentage of wasted space due to suboptimal ordering of struct
fields, if this figure is 20% or higher:
In the struct above, alignment rules require each of the two boolean
fields (1 byte) to occupy a complete word (8 bytes), leading to (7 +
7) / (3 * 8) = 58% waste.
Placing the two booleans together would save a word.
(In most structures clarity is more important than compactness, so you
should reorder fields to save space only in data structures that have
been shown by profiling to be very frequently allocated.)
**Embed directives**: hovering over the file name pattern in
[`//go:embed` directive](https://pkg.go.dev/embed), for example
`*.html`, reveals the list of file names to which the wildcard
expands.
**Linkname directives**: a [`//go:linkname` directive](https://pkg.go.dev/cmd/compile#hdr-Compiler_Directives) creates a linker-level alias for another symbol.
Hovering over the directive shows information about the other symbol.
The hover information for symbols from the standard library added
after Go 1.0 states the Go release that added the symbol.
Settings:
- The [`hoverKind`](../settings.md#hoverKind) setting controls the verbosity of documentation.
- The [`linkTarget`](../settings.md#linkTarget) setting specifies
the base URI for Go package links
Caveats:
- It is an unfortunate limitation of the LSP that a `Hover` request
currently includes only a position but not a selection, as this
means it is impossible to request information about the type and
methods of, say, the `f(x)` portion of the larger expression
`f(x).y`. Please upvote microsoft/language-server-protocol#1466 if
you would like to see this addressed.
Client support:
- **VS Code**: enabled by default. Displays rendered Markdown in a panel near the cursor.
- **Emacs + eglot**: enabled by default. Displays a one-line summary in the echo area.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls definition file.go:#start-#end` includes information from a Hover query.
## Signature Help
The LSP [`textDocument/signatureHelp`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_signatureHelp)
query returns information about the innermost function call enclosing
the cursor or selection, including the signature of the function and
the names, types, and documentation of each parameter.
Clients may provide this information to help remind the user of the
purpose of each parameter and their order, while reading or editing a
function call.
Call parens are not necessary if the cursor is within an identifier
that denotes a function or method. For example, Signature Help at
`once.Do(initialize‸)` will describe `initialize`, not `once.Do`.
Client support:
- **VS Code**: enabled by default.
Also known as "[parameter hints](https://code.visualstudio.com/api/references/vscode-api#SignatureHelpProvider)" in the [IntelliSense settings](https://code.visualstudio.com/docs/editor/intellisense#_settings).
Displays signature and doc comment alongside Hover information.
- **Emacs + eglot**: enabled by default. Displays signature in the echo area.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls signature file.go:#start-#end`
## Document Highlight
The LSP [`textDocument/documentHighlight`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentHighlight)
query reports a set of source ranges that should be highlighted based
on the current cursor position or selection, to emphasize the
relationship between them.
Each of the following parts of syntax forms a set so that if you
select any one member, gopls will highlight the complete set:
- each identifier that refers to the same symbol (as in the screenshot below);
- a named result variable and all its corresponding operands of `return` statements;
- the `for`, `break`, and `continue` tokens of the same loop;
- the `switch` and `break` tokens of the same switch statement;
- the `func` keyword of a function and all of its `return` statements.
More than one of these rules may be activated by a single selection,
for example, by an identifier that is also a return operand.
Different occurrences of the same identifier may be color-coded to distinguish
"read" from "write" references to a given variable symbol.
Client support:
- **VS Code**: enabled by default. Triggered by cursor motion, or single click.
(Note: double clicking activates a simple syntax-oblivious textual match.)
- **Emacs + eglot**: enabled by default. Triggered by cursor motion or selection.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls signature file.go:#start-#end`
## Inlay Hint
The LSP [`textDocument/inlayHint`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_inlayHint)
query returns a set of annotations to be spliced into the current file
that reveal implicit information.
Examples:
- In a function call `f(1, 2)`, hints provide the
names of the parameters (`parameterNames`), as in the screenshot above.
- In a call to a generic function, hints provide the type arguments
(`functionTypeParameters`).
- In an assignment `x, y = 1, 2`, hints provide the types of the
variables (`assignVariableTypes`).
- In a struct literal such as `Point2D{1, 2}`, hints provide the field
names (`compositeLiteralFields`).
- In a nested composite literal `T{{...}}`, a hint provides the type of
the inner literal, `{...}` (`compositeLiteralTypes`).
- In a `for k, v := range x {}` loop, hints provide the types of the
variables k and v (`rangeVariableTypes`).
- For a constant expression (perhaps using `iota`), a hint provides
its computed value (`constantValues`).
See [Inlay hints](../inlayHints.md) for a complete list with examples.
Settings:
- The [`hints`](../settings.md#hints) setting indicates the desired set of hints.
To reduce distractions, its default value is empty.
To enable hints, add one or more of the identifiers above to the hints
map. For example:
```json5
"hints": {"parameterNames": true}
```
Client support:
- **VS Code**: in addition to the `hints` configuration value, VS Code provides a graphical
configuration menu ("Preferences: Open Settings (UI)" the search for "Go Inlay Hints")
for each supported kind of inlay hint.
- **Emacs + eglot**: disabled by default. Needs `M-x eglot-inlay-hints-mode` plus the configuration [described here](https://www.reddit.com/r/emacs/comments/11bqzvk/emacs29_and_eglot_inlay_hints/)
- **Vim + coc.nvim**: ??
- **CLI**: not supported
## Semantic Tokens
The LSP [`textDocument/semanticTokens`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_semanticTokens)
query reports information about all the tokens in the current file, or
a portion of it.
The client may use this information to provide syntax highlighting
that conveys semantic distinctions between, for example, functions and
types, constants and variables, or library functions and built-ins.
The client must specify the sets of types and modifiers it is interested in.
Gopls reports the following token types:
- `"comment"`: a comment
- `"function"`: a function
- `"keyword"`: a keyword
- `"label"`: a control label (not an LSP standard type)
- `"macro"`: text/template tokens
- `"method"`: a method
- `"namespace"`: an imported package name
- `"number"`: a numeric literal
- `"operator"`: an operator
- `"parameter"`: a parameter variable
- `"string"`: a string literal
- `"type"`: a type name (plus other uses)
- `"typeParameter"`: a type parameter
- `"variable"`: a var or const (see `readonly` modifier)
Gopls also reports the following standard modifiers:
- `"defaultLibrary"`: predeclared symbols
- `"definition"`: the declaring identifier of a symbol
- `"readonly"`: for constants
plus these non-standard modifiers each representing the top-level
constructor of each symbols's type:
- `"array"`
- `"bool"`
- `"chan"`
- `"interface"`
- `"map"`
- `"number"`
- `"pointer"`
- `"signature"`
- `"slice"`
- `"string"`
- `"struct"`
Settings:
- The [`semanticTokens`](../settings.md#semanticTokens) setting determines whether
gopls responds to semantic token requests. This option allows users to disable
semantic tokens even when their client provides no client-side control over the
feature. Because gopls' semantic-tokens algorithm depends on type checking,
which adds a tangible latency, this feature is currently disabled by default
to avoid any delay in syntax highlighting; see https://go.dev/issue/#45313, https://go.dev/issue/#47465.
- The experimental [`noSemanticString`](../settings.md#noSemanticString) and
[`noSemanticNumber`](../settings.md#noSemanticNumber) settings cause the server
to exclude the `string` and `number` kinds from the response, as some clients
may do a more colorful job highlighting these tokens; see https://go.dev/issue/45753.
Client Support:
- **VS Code**: See [Semantic Highlighting Guide](https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide).
- **Emacs + eglot**: Not supported; see joaotavora/eglot#615.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls semtok file.go`
## Folding Range
The LSP [`textDocument/foldingRange`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_foldingRange)
query reports the list of regions in the current file that may be
independently collapsed or expanded. For example, it may be convenient
to collapse large comments or functions when studying some code so
that more of it fits in a single screen.
The protocol [allows](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#foldingRangeClientCapabilities) clients to indicate whether they prefer
fine-grained ranges such as matched pairs of brackets, or only ranges
consisting of complete lines.
Client support:
- **VS Code**: displayed in left margin. Toggle the chevrons (`∨` and `>`) to collapse or expand.
- **Emacs + eglot**: not supported.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls folding_ranges file.go`
## Document Link
The LSP [`textDocument/documentLink`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentLink)
query uses heuristics to extracts URLs from doc comments and string
literals in the current file so that the client can present them as
clickable links.
In addition to explicit URLs, gopls also turns string literals in
import declarations into links to the pkg.go.dev documentation for the
imported package.
Settings:
- The [`importShortcut`](../settings.md#importShortcut) setting determines
what kind of link is returned for an `import` declaration.
- The [`linkTarget`](../settings.md#linkTarget) setting specifies
the base URI for Go package links.
Client support:
- **VS Code**: Hovering over a link displays a "Follow link (cmd+click)" popup.
- **Emacs + eglot**: not currently used.
- **Vim + coc.nvim**: ??
- **CLI**: `gopls links file.go`
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/templates.md
---
title: "Gopls: Support for template files"
---
Gopls provides some support for Go template files, that is, files that
are parsed by [`text/template`](https://pkg.go.dev/text/template) or
[`html/template`](https://pkg.go.dev/html/template).
## Enabling template support
Gopls recognizes template files based on their file extension, which
may be configured by the
[`templateExtensions`](../settings.md#templateExtensions) setting. If
this list is empty, template support is disabled. (This is the default
value, since Go templates don't have a canonical file extension.)
Additional configuration may be necessary to ensure that your client
chooses the correct language kind when opening template files.
Gopls recognizes both `"tmpl"` and `"gotmpl"` for template files.
For example, in `VS Code` you will also need to add an
entry to the
[`files.associations`](https://code.visualstudio.com/docs/languages/identifiers)
mapping:
```json
"files.associations": {
".mytemplate": "gotmpl"
},
```
## Features
In template files, template support works inside
the default `{{` delimiters. (Go template parsing
allows the user to specify other delimiters, but
gopls does not know how to do that.)
Gopls template support includes the following features:
+ **Diagnostics**: if template parsing returns an error,
it is presented as a diagnostic. (Missing functions do not produce errors.)
+ **Syntax Highlighting**: syntax highlighting is provided for template files.
+ **Definitions**: gopls provides jump-to-definition inside templates, though it does not understand scoping (all templates are considered to be in one global scope).
+ **References**: gopls provides find-references, with the same scoping limitation as definitions.
+ **Completions**: gopls will attempt to suggest completions inside templates.
TODO: also
+ Hover
+ SemanticTokens
+ Symbol search
+ DocumentHighlight
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/transformation.md
---
title: "Gopls: Code transformation features"
---
This document describes gopls' features for code transformation, which
include a range of behavior-preserving changes (refactorings,
formatting, simplifications), code repair (fixes), and editing support
(filling in struct literals and switch statements).
Code transformations are not a single category in the LSP:
- A few, such as Formatting and Rename, are primary operations in the
protocol.
- Some transformations are exposed through [Code Lenses](../codelenses.md),
which return _commands_, arbitrary server
operations invoked for their side effects through a
[`workspace/executeCommand`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_executeCommand) request;
however, no current code lenses are transformations of Go syntax.
- Most transformations are defined as *code actions*.
## Code Actions
A **code action** is an action associated with a portion of the file.
Each time the selection changes, a typical client makes a
[`textDocument/codeAction`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_codeAction)
request for the set of available actions, then updates its UI
elements (menus, icons, tooltips) to reflect them.
The VS Code manual describes code actions as
"[Quick fixes + Refactorings](https://code.visualstudio.com/docs/editor/refactoring#_code-actions-quick-fixes-and-refactorings)".
A `codeAction` request delivers the menu, so to speak, but it does
not order the meal. Once the user chooses an action, one of two things happens.
In trivial cases, the action itself contains an edit that the
client can directly apply to the file.
But in most cases the action contains a command,
similar to the command associated with a code lens.
This allows the work of computing the patch to be done lazily, only
when actually needed. (Most aren't.)
The server may then compute the edit and send the client a
[`workspace/applyEdit`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_applyEdit)
request to patch the files.
Not all code actions' commands have an `applyEdit` side effect: some
may change the state of the server, for example to toggle a variable
or to cause the server to send other requests to the client,
such as a `showDocument` request to open a report in a web browser.
The main difference between code lenses and code actions is this:
- a `codeLens` request obtains commands for the entire file.
Each command specifies its applicable source range,
and typically appears as an annotation on that source range.
- a `codeAction` request obtains commands only for a particular range: the current selection.
All the commands are presented together in a menu at that location.
Each action has a _kind_,
which is a hierarchical identifier such as `refactor.inline.call`.
Clients may filter actions based on their kind.
For example, VS Code has:
two menus, "Refactor..." and "Source action...", each populated by
different kinds of code actions (`refactor` and `source`);
a lightbulb icon that triggers a menu of "quick fixes" (of kind `quickfix`);
and a "Fix All" command that executes all code actions of
kind `source.fixAll`, which are those deemed unambiguously safe to apply.
Gopls supports the following code actions:
- `quickfix`, which applies unambiguously safe fixes
- [`source.organizeImports`](#source.organizeImports)
- [`source.assembly`](web.md#assembly)
- [`source.doc`](web.md#doc)
- [`source.freesymbols`](web.md#freesymbols)
- `source.test` (undocumented)
- [`source.addTest`](#source.addTest)
- [`source.toggleCompilerOptDetails`](diagnostics.md#toggleCompilerOptDetails)
- [`gopls.doc.features`](README.md), which opens gopls' index of features in a browser
- [`refactor.extract.constant`](#extract)
- [`refactor.extract.function`](#extract)
- [`refactor.extract.method`](#extract)
- [`refactor.extract.toNewFile`](#extract.toNewFile)
- [`refactor.extract.variable`](#extract)
- [`refactor.extract.variable-all`](#extract)
- [`refactor.inline.call`](#refactor.inline.call)
- [`refactor.inline.variable`](#refactor.inline.variable)
- [`refactor.rewrite.addTags`](#refactor.rewrite.addTags)
- [`refactor.rewrite.changeQuote`](#refactor.rewrite.changeQuote)
- [`refactor.rewrite.fillStruct`](#refactor.rewrite.fillStruct)
- [`refactor.rewrite.fillSwitch`](#refactor.rewrite.fillSwitch)
- [`refactor.rewrite.invertIf`](#refactor.rewrite.invertIf)
- [`refactor.rewrite.joinLines`](#refactor.rewrite.joinLines)
- [`refactor.rewrite.moveParamLeft`](#refactor.rewrite.moveParamLeft)
- [`refactor.rewrite.moveParamRight`](#refactor.rewrite.moveParamRight)
- [`refactor.rewrite.removeTags`](#refactor.rewrite.removeTags)
- [`refactor.rewrite.removeUnusedParam`](#refactor.rewrite.removeUnusedParam)
- [`refactor.rewrite.splitLines`](#refactor.rewrite.splitLines)
Gopls reports some code actions twice, with two different kinds, so
that they appear in multiple UI elements: simplifications,
for example from `for _ = range m` to `for range m`,
have kinds `quickfix` and `source.fixAll`,
so they appear in the "Quick Fix" menu and
are activated by the "Fix All" command.
Many transformations are computed by [analyzers](../analyzers.md)
that, in the course of reporting a diagnostic about a problem,
also suggest a fix.
A `codeActions` request will return any fixes accompanying diagnostics
for the current selection.
Caveats:
- Many of gopls code transformations are limited by Go's syntax tree
representation, which currently records comments not in the tree
but in a side table; consequently, transformations such as Extract
and Inline are prone to losing comments. This is issue
https://go.dev/issue/20744, and it is a priority for us to fix in 2024.
- Generated files, as identified by the conventional
[DO NOT EDIT](https://go.dev/s/generatedcode) comment,
are not offered code actions for transformations.
Client support for code actions:
- **VS Code**: Depending on their kind, code actions are found in
the "Refactor..." menu (`^⇧R`),
the "Source action..." menu,
the 💡 (light bulb) icon's menu, or
the "Quick fix" (`⌘.`) menu.
The "Fix All" command applies all actions of kind `source.fixAll`.
- **Emacs + eglot**: Code actions are invisible.
Use `M-x eglot-code-actions` to select one from those that are
available (if there are multiple) and execute it.
Some action kinds have filtering shortcuts,
e.g. [`M-x eglot-code-action-{inline,extract,rewrite}`](https://joaotavora.github.io/eglot/#index-M_002dx-eglot_002dcode_002daction_002dinline).
- **CLI**: `gopls codeaction -exec -kind k,... -diff file.go:#123-#456` executes code actions of the specified
kinds (e.g. `refactor.inline`) on the selected range, specified using zero-based byte offsets, and displays the diff.
## Formatting
The LSP
[`textDocument/formatting`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_formatting)
request returns edits that format a file.
Gopls applies Go's canonical formatting algorithm,
[`go fmt`](https://pkg.go.dev/cmd/gofmt).
LSP formatting options are ignored.
Most clients are configured to format files and organize imports
whenever a file is saved.
Settings:
- The [`gofumpt`](../settings.md#gofumpt) setting causes gopls to use an
alternative formatter, [`github.com/mvdan/gofumpt`](https://pkg.go.dev/mvdan.cc/gofumpt).
Client support:
- **VS Code**: Formats on save by default. Use `Format document` menu item (`⌥⇧F`) to invoke manually.
- **Emacs + eglot**: Use `M-x eglot-format-buffer` to format. Attach it to `before-save-hook` to format on save. For formatting combined with organize-imports, many users take the legacy approach of setting `"goimports"` as their `gofmt-command` using [go-mode](https://github.com/dominikh/go-mode.el), and adding `gofmt-before-save` to `before-save-hook`. An LSP-based solution requires code such as https://github.com/joaotavora/eglot/discussions/1409.
- **CLI**: `gopls format file.go`
## `source.organizeImports`: Organize imports
A `codeActions` request in a file whose imports are not organized will
return an action of the standard kind `source.organizeImports`.
Its command has the effect of organizing the imports:
deleting existing imports that are duplicate or unused,
adding new ones for undefined symbols,
and sorting them into the conventional order.
The addition of new imports is based on heuristics that depend on
your workspace and the contents of your GOMODCACHE directory; they may
sometimes make surprising choices.
Many editors automatically organize imports and format the code before
saving any edited file.
Some users dislike the automatic removal of imports that are
unreferenced because, for example, the sole line that refers to the
import is temporarily commented out for debugging; see https://go.dev/issue/54362.
Settings:
- The [`local`](../settings.md#local) setting is a comma-separated list of
prefixes of import paths that are "local" to the current file and
should appear after standard and third-party packages in the sort order.
Client support:
- **VS Code**: automatically invokes `source.organizeImports` before save.
To disable it, use the snippet below, and invoke the "Organize Imports" command manually as needed.
```
"[go]": {
"editor.codeActionsOnSave": { "source.organizeImports": false }
}
```
- **Emacs + eglot**: Use `M-x eglot-code-action-organize-imports` to invoke manually.
Many users of [go-mode](https://github.com/dominikh/go-mode.el) use these lines to
organize imports and reformat each modified file before saving it, but this
approach is based on the legacy
[`goimports`](https://pkg.go.dev/golang.org/x/tools/cmd/goimports) tool, not gopls:
```lisp
(setq gofmt-command "goimports")
(add-hook 'before-save-hook 'gofmt-before-save)
```
- **CLI**: `gopls fix -a file.go:#offset source.organizeImports`
## `source.addTest`: Add test for function or method
If the selected chunk of code is part of a function or method declaration F,
gopls will offer the "Add test for F" code action, which adds a new test for the
selected function in the corresponding `_test.go` file. The generated test takes
into account its signature, including input parameters and results.
**Test file**: if the `_test.go` file does not exist, gopls creates it, based on
the name of the current file (`a.go` -> `a_test.go`), copying any copyright and
build constraint comments from the original file.
**Test package**: for new files that test code in package `p`, the test file
uses `p_test` package name whenever possible, to encourage testing only exported
functions. (If the test file already exists, the new test is added to that file.)
**Parameters**: each of the function's non-blank parameters becomes an item in
the struct used for the table-driven test. (For each blank `_` parameter, the
value has no effect, so the test provides a zero-valued argument.)
**Contexts**: If the first parameter is `context.Context`, the test passes
`context.Background()`.
**Results**: the function's results are assigned to variables (`got`, `got2`,
and so on) and compared with expected values (`want`, `want2`, etc.`) defined in
the test case struct. The user should edit the logic to perform the appropriate
comparison. If the final result is an `error`, the test case defines a `wantErr`
boolean.
**Method receivers**: When testing a method `T.F` or `(*T).F`, the test must
construct an instance of T to pass as the receiver. Gopls searches the package
for a suitable function that constructs a value of type T or \*T, optionally with
an error, preferring a function named `NewT`.
**Imports**: Gopls adds missing imports to the test file, using the last
corresponding import specifier from the original file. It avoids duplicate
imports, preserving any existing imports in the test file.
## Rename
The LSP
[`textDocument/rename`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_rename)
request renames a symbol.
Renaming is a two-stage process. The first step, a
[`prepareRename`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_prepareRename) query, returns the current
name of the identifier under the cursor (if indeed there is one).
The client then displays a dialog prompting the user to choose a new
name by editing the old one. The second step, `rename` proper, applies
the changes. (This simple dialog support is unique among LSP
refactoring operations; see microsoft/language-server-protocol#1164.)
Gopls' renaming algorithm takes great care to detect situations in
which renaming might introduce a compilation error.
For example, changing a name may cause a symbol to become "shadowed",
so that some existing references are no longer in scope. Gopls will
report an error, stating the pair of symbols and the shadowed reference:
As another example, consider renaming a method of a concrete type.
Renaming may cause the type to no longer satisfy the same interfaces
as before, which could cause the program to fail to compile.
To avoid this, gopls inspects each conversion (explicit or implicit)
from the affected type to an interface type, and checks whether it
would remain valid after the renaming. If not, it aborts the renaming
with an error.
If you intend to rename both the original method and the corresponding
methods of any matching interface types (as well as any methods of
types matching them in turn), you can indicate this by invoking the
rename operation on the interface method.
Similarly, gopls will report an error if you rename a field of a
struct that happens to be an "anonymous" field that embeds a type,
since that would require a larger renaming involving the type as well.
If that is what you intend, you can again indicate this by
invoking the rename operation on the type.
Renaming should never introduce a compilation error, but it may
introduce dynamic errors. For example, in a method renaming, if there
is no direct conversion of the affected type to the interface type,
but there is an intermediate conversion to a broader type (such as `any`) followed by a
type assertion to the interface type, then gopls may proceed to rename
the method, causing the type assertion to fail at run time.
Similar problems may arise with packages that use reflection, such as
`encoding/json` or `text/template`. There is no substitute for good
judgment and testing.
Special cases:
- When renaming the declaration of a method receiver, the tool also
attempts to rename the receivers of all other methods associated
with the same named type. Each other receiver that cannot be fully
renamed is quietly skipped. Renaming any _use_ of a receiver affects
only that variable.
```go
type Counter struct { x int }
Rename here to affect only this method
↓
func (c *Counter) Inc() { c.x++ }
func (c *Counter) Dec() { c.x++ }
↑
Rename here to affect all methods
```
Using Rename to move a package:
To rename a package, execute the Rename operation over the `p` in a
`package p` declaration at the start of a file.
You will be prompted to edit the package's path and choose its new location.
The Rename operation will move all the package's files to the resulting directory,
creating it if necessary.
By default, subpackages will remain where they are. To include subpackages
in the renaming, set [renameMovesSubpackages](../settings.md#renamemovessubpackages-bool) to true.
Existing imports of the package will be updated to reflect its new path.
Package moves are rejected if they would break the build. For example:
- Packages cannot move across a module boundary.
- Packages cannot be moved into existing packages; gopls does not support package merging.
- Packages cannot be moved to internal directories that would make them inaccessible to any of their current importers.
Renaming package main is not supported, because the main package has special meaning to the linker.
Renaming x_test packages is currently not supported.
Some tips for best results:
- The safety checks performed by the Rename algorithm require type
information. If the program is grossly malformed, there may be
insufficient information for it to run (https://go.dev/issue/41870),
and renaming cannot generally be used to fix a type error (https://go.dev/issue/41851).
When refactoring, we recommend working in small steps, repairing any
problems as you go, so that as much as possible of the program
compiles at each step.
- Sometimes it may be desirable for a renaming operation to change the
reference structure of the program, for example to intentionally
combine two variables x and y by renaming y to x.
The renaming tool is too strict to help in this case (https://go.dev/issue/41852).
For the gory details of gopls' rename algorithm, you may be interested
in the latter half of this 2015 GothamGo talk:
[Using go/types for Code Comprehension and Refactoring Tools](https://www.youtube.com/watch?v=p_cz7AxVdfg).
Client support:
- **VS Code**: Use "[Rename symbol](https://code.visualstudio.com/docs/editor/editingevolved#_rename-symbol)" menu item (`F2`).
- **Emacs + eglot**: Use `M-x eglot-rename`, or `M-x go-rename` from [go-mode](https://github.com/dominikh/go-mode.el).
- **Vim + coc.nvim**: Use the `coc-rename` command.
- **CLI**: `gopls rename file.go:#offset newname`
## `refactor.extract`: Extract function/method/variable
The `refactor.extract` family of code actions all return commands that
replace the selected expression or statements with a reference to a
newly created declaration that contains the selected code:
- **`refactor.extract.function`** replaces one or more complete statements by a
call to a new function named `newFunction` whose body contains the
statements. The selection must enclose fewer statements than the
entire body of the existing function.


- **`refactor.extract.method`** is a variant of "Extract function" offered when
the selected statements belong to a method. The newly created function
will be a method of the same receiver type.
- **`refactor.extract.variable`** replaces an expression by a reference to a new
local variable named `newVar` initialized by the expression:


- **`refactor.extract.constant** does the same thing for a constant
expression, introducing a local const declaration.
- **`refactor.extract.variable-all`** replaces all occurrences of the selected expression
within the function with a reference to a new local variable named `newVar`.
This extracts the expression once and reuses it wherever it appears in the function.


- **`refactor.extract.constant-all** does the same thing for a constant
expression, introducing a local const declaration.
If the default name for the new declaration is already in use, gopls
generates a fresh name.
Extraction is a challenging problem requiring consideration of
identifier scope and shadowing, control
flow such as `break`/`continue` in a loop or `return` in a
function, cardinality of variables, and even subtle issues of style.
In each case, the tool will try to update the extracted statements
as needed to avoid build breakage or behavior changes.
Unfortunately, gopls' Extract algorithms are considerably less
rigorous than the Rename and Inline operations, and we are aware of a
number of cases where it falls short, including:
- https://github.com/golang/go/issues/66289
- https://github.com/golang/go/issues/65944
- https://github.com/golang/go/issues/63394
- https://github.com/golang/go/issues/61496
The following Extract features are planned for 2024 but not yet supported:
- **Extract parameter struct** will replace two or more parameters of a
function by a struct type with one field per parameter; see https://go.dev/issue/65552.
- **Extract interface for type** will create a declaration of an
interface type with all the methods of the selected concrete type;
see https://go.dev/issue/65721 and https://go.dev/issue/46665.
## `refactor.extract.toNewFile`: Extract declarations to new file
(Available from gopls/v0.17.0)
If you select one or more top-level declarations, gopls will offer an
"Extract declarations to new file" code action that moves the selected
declarations into a new file whose name is based on the first declared
symbol.
Import declarations are created as needed.
Gopls also offers this code action when the selection is just the
first token of the declaration, such as `func` or `type`.


## `refactor.inline.call`: Inline call to function
For a `codeActions` request where the selection is (or is within) a
call of a function or method, gopls will return a command of kind
`refactor.inline.call`, whose effect is to inline the function call.
The screenshots below show a call to `sum` before and after inlining:


Inlining replaces the call expression by a copy of the function body,
with parameters replaced by arguments.
Inlining is useful for a number of reasons.
Perhaps you want to eliminate a call to a deprecated
function such as `ioutil.ReadFile` by replacing it with a call to the
newer `os.ReadFile`; inlining will do that for you.
Or perhaps you want to copy and modify an existing function in some
way; inlining can provide a starting point.
The inlining logic also provides a building block for
other refactorings, such as "change signature".
Not every call can be inlined.
Of course, the tool needs to know which function is being called, so
you can't inline a dynamic call through a function value or interface
method; but static calls to methods are fine.
Nor can you inline a call if the callee is declared in another package
and refers to non-exported parts of that package, or to [internal
packages](https://go.dev/doc/go1.4#internalpackages) that are
inaccessible to the caller.
Calls to generic functions are not yet supported
(https://go.dev/issue/63352), though we plan to fix that.
When inlining is possible, it's critical that the tool preserve
the original behavior of the program.
We don't want refactoring to break the build, or, worse, to introduce
subtle latent bugs.
This is especially important when inlining tools are used to perform
automated clean-ups in large code bases;
we must be able to trust the tool.
Our inliner is very careful not to make guesses or unsound
assumptions about the behavior of the code.
However, that does mean it sometimes produces a change that differs
from what someone with expert knowledge of the same code might have
written by hand.
In the most difficult cases, especially with complex control flow, it
may not be safe to eliminate the function call at all.
For example, the behavior of a `defer` statement is intimately tied to
its enclosing function call, and `defer` is the only control
construct that can be used to handle panics, so it cannot be reduced
into simpler constructs.
So, for example, given a function f defined as:
```go
func f(s string) {
defer fmt.Println("goodbye")
fmt.Println(s)
}
```
a call `f("hello")` will be inlined to:
```go
func() {
defer fmt.Println("goodbye")
fmt.Println("hello")
}()
```
Although the parameter was eliminated, the function call remains.
An inliner is a bit like an optimizing compiler.
A compiler is considered "correct" if it doesn't change the meaning of
the program in translation from source language to target language.
An _optimizing_ compiler exploits the particulars of the input to
generate better code, where "better" usually means more efficient.
As users report inputs that cause the compiler to emit suboptimal
code, the compiler is improved to recognize more cases, or more rules,
and more exceptions to rules---but this process has no end.
Inlining is similar, except that "better" code means tidier code.
The most conservative translation provides a simple but (hopefully)
correct foundation, on top of which endless rules, and exceptions to
rules, can embellish and improve the quality of the output.
Here are some of the technical challenges involved in sound inlining:
- **Effects:** When replacing a parameter by its argument expression,
we must be careful not to change the effects of the call. For
example, if we call a function `func twice(x int) int { return x + x }`
with `twice(g())`, we do not want to see `g() + g()`, which would
cause g's effects to occur twice, and potentially each call might
return a different value. All effects must occur the same number of
times, and in the same order. This requires analyzing both the
arguments and the callee function to determine whether they are
"pure", whether they read variables, or whether (and when) they
update them too. The inliner will introduce a declaration such as
`var x int = g()` when it cannot prove that it is safe to substitute
the argument throughout.
- **Constants:** If inlining always replaced a parameter by its argument
when the value is constant, some programs would no longer build
because checks previously done at run time would happen at compile time.
For example `func index(s string, i int) byte { return s[i] }`
is a valid function, but if inlining were to replace the call `index("abc", 3)`
by the expression `"abc"[3]`, the compiler will report that the
index `3` is out of bounds for the string `"abc"`.
The inliner will prevent substitution of parameters by problematic
constant arguments, again introducing a `var` declaration instead.
- **Referential integrity:** When a parameter variable is replaced by
its argument expression, we must ensure that any names in the
argument expression continue to refer to the same thing---not to a
different declaration in the callee function body that happens to
use the same name. The inliner must replace local references such as
`Printf` by qualified references such as `fmt.Printf`, and add an
import of package `fmt` as needed.
- **Implicit conversions:** When passing an argument to a function, it is
implicitly converted to the parameter type. If we eliminate the parameter
variable, we don't want to lose the conversion as it may be important. For
example, in `func f(x any) { y := x; fmt.Printf("%T", &y) }` the type of
variable y is `any`, so the program prints `"*interface{}"`. But if inlining
the call `f(1)` were to produce the statement `y := 1`, then the type of y
would have changed to `int`, which could cause a compile error or, as in this
case, a bug, as the program now prints `"*int"`. When the inliner substitutes
a parameter variable by its argument value, it may need to introduce explicit
conversions of each value to the original parameter type, such as `y :=
any(1)`.
- **Last reference:** When an argument expression has no effects
and its corresponding parameter is never used, the expression
may be eliminated. However, if the expression contains the last
reference to a local variable at the caller, this may cause a compile
error because the variable is now unused. So the inliner must be
cautious about eliminating references to local variables.
This is just a taste of the problem domain. If you're curious, the
documentation for [golang.org/x/tools/internal/refactor/inline](https://pkg.go.dev/golang.org/x/tools/internal/refactor/inline) has
more detail. All of this is to say, it's a complex problem, and we aim
for correctness first of all. We've already implemented a number of
important "tidiness optimizations" and we expect more to follow.
## `refactor.inline.variable`: Inline local variable
For a `codeActions` request where the selection is (or is within) an
identifier that is a use of a local variable whose declaration has an
initializer expression, gopls will return a code action of kind
`refactor.inline.variable`, whose effect is to inline the variable:
that is, to replace the reference by the variable's initializer
expression.
For example, if invoked on the identifier `s` in the call `println(s)`:
```go
func f(x int) {
s := fmt.Sprintf("+%d", x)
println(s)
}
```
the code action transforms the code to:
```go
func f(x int) {
s := fmt.Sprintf("+%d", x)
println(fmt.Sprintf("+%d", x))
}
```
(In this instance, `s` becomes an unreferenced variable which you will
need to remove.)
The code action always replaces the reference by the initializer
expression, even if there are later assignments to the variable (such
as `s = ""`).
The code action reports an error if it is not possible to make the
transformation because one of the identifiers within the initializer
expression (e.g. `x` in the example above) is shadowed by an
intervening declaration, as in this example:
```go
func f(x int) {
s := fmt.Sprintf("+%d", x)
{
x := 123
println(s, x) // error: cannot replace s with fmt.Sprintf(...) since x is shadowed
}
}
```
## `refactor.rewrite`: Miscellaneous rewrites
This section covers a number of transformations that are accessible as
code actions whose kinds are children of `refactor.rewrite`.
### `refactor.rewrite.removeUnusedParam`: Remove unused parameter
The [`unusedparams` analyzer](../analyzers.md#unusedparams) reports a
diagnostic for each parameter that is not used within the function body.
For example:
```go
func f(x, y int) { // "unused parameter: x"
fmt.Println(y)
}
```
It does _not_ report diagnostics for address-taken functions, which
may need all their parameters, even unused ones, in order to conform
to a particular function signature.
Nor does it report diagnostics for exported functions,
which may be address-taken by another package.
(A function is _address-taken_ if it is used other than in call position, `f(...)`.)
In addition to the diagnostic, it suggests two possible fixes:
1. rename the parameter to `_` to emphasize that it is unreferenced (an immediate edit); or
2. delete the parameter altogether, using a `ChangeSignature` command, updating all callers.
Fix \#2 uses the same machinery as "Inline function call" (see above)
to ensure that the behavior of all existing calls is preserved, even
when the argument expression for the deleted parameter has side
effects, as in the example below.


Observe that in the first call, the argument `chargeCreditCard()` was
not deleted because of potential side effects, whereas in the second
call, the argument 2, a constant, was safely deleted.
### `refactor.rewrite.moveParam{Left,Right}`: Move function parameters
When the selection is a parameter in a function or method signature, gopls
offers a code action to move the parameter left or right (if feasible),
updating all callers accordingly.
For example:
```go
func Foo(x, y int) int {
return x + y
}
func _() {
_ = Foo(0, 1)
}
```
becomes
```go
func Foo(y, x int) int {
return x + y
}
func _() {
_ = Foo(1, 0)
}
```
following a request to move `x` right, or `y` left.
This is a primitive building block of more general "Change signature"
operations. We plan to generalize this to arbitrary signature rewriting, but
the language server protocol does not currently offer good support for user
input into refactoring operations (see
[microsoft/language-server-protocol#1164](https://github.com/microsoft/language-server-protocol/issues/1164)).
Therefore, any such refactoring will require custom client-side logic. (As a
very hacky workaround, you can express arbitrary parameter movement by invoking
Rename on the `func` keyword of a function declaration, but this interface is
just a temporary stopgap.)
### `refactor.rewrite.changeQuote`: Convert string literal between raw and interpreted
When the selection is a string literal, gopls offers a code action
to convert the string between raw form (`` `abc` ``) and interpreted
form (`"abc"`) where this is possible:


Applying the code action a second time reverts back to the original
form.
### `refactor.rewrite.invertIf`: Invert 'if' condition
When the selection is within an `if`/`else` statement that is not
followed by `else if`, gopls offers a code action to invert the
statement, negating the condition and swapping the `if` and and `else`
blocks.


### `refactor.rewrite.{split,join}Lines`: Split elements into separate lines
When the selection is within a bracketed list of items such as:
- the **elements** of a composite literal, `[]T{a, b, c}`,
- the **arguments** of a function call, `f(a, b, c)`,
- the **groups of parameters** of a function signature, `func(a, b, c int, d, e bool)`, or
- its **groups of results**, `func() (x, y string, z rune)`,
gopls will offer the "Split [items] into separate lines" code
action, which would transform the forms above into these forms:
```go
[]T{
a,
b,
c,
}
f(
a,
b,
c,
)
func(
a, b, c int,
d, e bool,
)
func() (
x, y string,
z rune,
)
```
Observe that in the last two cases, each
[group](https://pkg.go.dev/go/ast#Field) of parameters or results is
treated as a single item.
The opposite code action, "Join [items] into one line", undoes the operation.
Neither action is offered if the list is already full split or joined,
respectively, or trivial (fewer than two items).
These code actions are not offered for lists containing `//`-style
comments, which run to the end of the line.
### `refactor.rewrite.fillStruct`: Fill struct literal
When the cursor is within a struct literal `S{}`, gopls offers the
"Fill S" code action, which populates each missing field of the
literal that is accessible.
It uses the following heuristic to choose the value assigned to each
field: it finds candidate variables, constants, and functions that are
assignable to the field, and picks the one whose name is the closest
match to the field name.
If there are none, it uses the zero value (such as `0`, `""`, or
`nil`) of the field's type.
In the example below, a
[`slog.HandlerOptions`](https://pkg.go.dev/golang.org/x/exp/slog#HandlerOptions)
struct literal is filled in using two local variables (`level` and
`add`) and a function (`replace`):


Caveats:
- This code action requires type information for the struct type, so
if it is defined in another package that is not yet imported, you
may need to "organize imports" first, for example by saving the
file.
- Candidate declarations are sought only in the current file, and only
above the current point. Symbols declared beneath the current point,
or in other files in the package, are not considered; see
https://go.dev/issue/68224.
### `refactor.rewrite.fillSwitch`: Fill switch
When the cursor is within a switch statement whose operand type is an
_enum_ (a finite set of named constants), or within a type switch,
gopls offers the "Add cases for T" code action, which populates the
switch statement by adding a case for each accessible named constant
of the enum type, or, for a type switch, by adding a case for each
accessible named non-interface type that implements the interface.
Only missing cases are added.
The screenshots below show a type switch whose operand has the
[`net.Addr`](https://pkg.go.dev/net#Addr) interface type. The code
action adds one case per concrete network address type, plus a default
case that panics with an informative message if an unexpected operand
is encountered.


And these screenshots illustrate the code action adding cases for each
value of the
[`html.TokenType`](https://pkg.go.dev/golang.org/x/net/html#TokenType)
enum type, which represents the various types of token from
which HTML documents are composed:


### `refactor.rewrite.eliminateDotImport`: Eliminate dot import
When the cursor is on a dot import gopls can offer the "Eliminate dot import"
code action, which removes the dot from the import and qualifies uses of the
package throughout the file. This code action is offered only if
each use of the package can be qualified without collisions with existing names.
### `refactor.rewrite.addTags`: Add struct tags
When the cursor is within a struct, this code action adds to each field a `json`
struct tag that specifies its JSON name, using lower case with underscores
(e.g. LinkTarget becomes link_target). For a highlighted selection, it only
adds tags on selected fields.
### `refactor.rewrite.removeTags`: Remove struct tags
When the cursor is within a struct, this code action clears struct tags on
all struct fields. For a highlighted selection, it removes tags from only
the selected fields.
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/features/web.md
---
title: "Gopls: Web-based features"
---
The LSP
[`window.showDocument`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#window_showDocument) request
allows the server to instruct the client to open a file in the editor
or a web page in a browser. It is the basis for a number of gopls
features that report information about your program through a web
interface.
We recognize that a web interface is not ideal for everyone: some
users prefer a full-screen editor layout and dislike switching
windows; others may work in a text-only terminal without a window
system, perhaps over remote ssh or on the Linux console.
Unfortunately, the LSP lacks several natural kinds of extensibility,
including the ability for servers to define:
- queries that [generalize a References
query](https://github.com/microsoft/language-server-protocol/issues/1911),
displaying results using similar UI elements;
- commands that [produce a stream of
text](https://github.com/joaotavora/eglot/discussions/1402), like a
typical shell command or compiler, that the client can redirect to
the editor's usual terminal-like UI element; or
- refactoring operations that, like Rename, [prompt the
user](https://github.com/microsoft/language-server-protocol/issues/1164)
for additional information.
The web-based UI can help fill these gaps until such time as the LSP
provides standard ways of implementing these features.
Gopls' web server listens on a `localhost` port. For security, all its
endpoints include a random string that serves as an authentication
token. The client, provided authenticated URLs by the server, will be
able to access your source code, but arbitrary processes running on
your machine will not.
Restarting the gopls process causes this secret to change, rendering
all existing previous URLs invalid; existing pages will display a banner
indicating that they have become disconnected.
TODO: combine the web server and the debug server; see https://go.dev/issue/68229.
Gopls supports two-way communication between the web browser and the
client editor. All of the web-based reports contain links to
declarations in your source code. Clicking on one of these links
causes gopls to send a `showDocument` request to your editor to open
the relevant source file at the appropriate line. This works even when
your source code has been modified but not saved.
(VS Code users: please upvote microsoft/vscode#208093 if you would
like your editor to raise its window when handling this event.)
## `source.doc`: Browse package documentation
In any Go source file, a code action request returns a command to
"Browse package documentation". This command opens a browser window
showing the documentation for the current Go package, presented using
a similar design to https://pkg.go.dev.
This allows you to preview the documentation for your packages, even
internal ones that may be unpublished externally. Reloading the page
updates the documentation to reflect your changes. It is not necessary
to save modified Go source files.
Clicking on the link for a package-level symbol or method, which in
`pkg.go.dev` would ordinarily take you to a source-code viewer such as
GitHub or Google Code Search, causes your editor to navigate to the
relevant source file and line.
Client support:
- **VS Code**: Use the "Source Action... > Browse documentation for package P" menu.
- **Emacs + eglot**: Use `M-x go-browse-doc` in [go-mode](https://github.com/dominikh/go-mode.el).
- **Vim + coc.nvim**: ??
## `source.freesymbols`: Browse free symbols
When studying code, either to understand it or to evaluate a different
organization or factoring, it is common to need to know what the
"inputs" are to a given chunk of code, either because you are
considering extracting it into its own function and want to know what
parameters it would take, or just to understand how one piece of a long
function relates to the preceding pieces.
If you select a chunk of code, and invoke the "Browse free symbols"
[code action](transformation.md#code-actions), your editor will
open a browser displaying a report on the free symbols of the
selection. A symbol is "free" if it is referenced from within the
selection but defined outside of it. In essence, these are the inputs
to the selected chunk.
The report classifies the symbols into imported, local, and
package-level symbols. The imported symbols are grouped by package,
and link to the documentation for the package, as described above.
Each of the remaining symbols is presented as a link that causes your
editor to navigate to its declaration.
TODO: explain dotted paths.
Client support:
- **VS Code**: Use the "Source Action... > Browse free symbols" menu.
- **Emacs + eglot**: Use `M-x go-browse-freesymbols` in [go-mode](https://github.com/dominikh/go-mode.el).
- **Vim + coc.nvim**: ??
## `source.assembly`: Browse assembly
When you're optimizing the performance of your code or investigating
an unexpected crash, it may sometimes be helpful to inspect the
assembly code produced by the compiler for a given Go function.
If you position the cursor or selection within a function f,
gopls offers the "Browse assembly for f" [code action](transformation.md#code-actions).
This opens a web-based listing of the assembly for the function, plus
any functions nested within it.
Each time you edit your source and reload the page, the current
package is recompiled and the listing is updated. It is not necessary
to save your modified files.
The compiler's target architecture is the same as the one gopls uses
when analyzing the file: typically, this is your machine's GOARCH, but
when viewing a file with a build tag, such as one named `foo_amd64.go`
or containing the comment `//go:build amd64`, the tags determine the
architecture.
Each instruction is displayed with a link that causes your editor to
navigate to the source line responsible for the instruction, according
to the debug information.
The example above shows the arm64 assembly listing of
[`time.NewTimer`](https://pkg.go.dev/time#NewTimer).
Observe that the indicated instruction links to a source location
inside a different function, `syncTimer`, because the compiler
inlined the call from `NewTimer` to `syncTimer`.
Browsing assembly is not yet supported for generic functions, package
initializers (`func init`), or functions in test packages.
(Contributions welcome!)
Client support:
- **VS Code**: Use the "Source Action... > Browse GOARCH assembly for f" menu.
- **Emacs + eglot**: Use `M-x go-browse-assembly` in [go-mode](https://github.com/dominikh/go-mode.el).
- **Vim + coc.nvim**: ??
## `source.splitPackage`: Split package into components
The web-based "Split package" tool can help you split a complex
package into two or more components, ensuring that the dependencies
among those components are acyclic.
Follow the instructions on the page to choose a set of named components,
assign each declaration to the most appropriate component, and then
visualize the dependencies between those components created by references
from one symbol to another.
The figure below shows the tool operating on the `fmt` package, which
could (in principle) be split into three subpackages, one for
formatting (`Printf` and friends), one for scanning (`Scanf`), and one
for their common dependencies.
(Try playing with the tool on this package: it's an instructive
exercise. The figure below shows the solution.)
The tool does not currently perform the code transformation (moving
declarations to new packages, renaming symbols to export them as
needed), but we hope to add that in a future release.
Client support:
- **VS Code**: Use the "Source Action... > Split package P" menu.
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/index.md
---
title: "Gopls: The language server for Go"
---
`gopls` (pronounced "Go please") is the official [language
server](https://langserver.org) for Go, developed by the Go team. It
provides a wide variety of [IDE features](features/) to any
[LSP](https://microsoft.github.io/language-server-protocol/)-compatible
editor.
You should not need to interact with `gopls` directly--it will be automatically
integrated into your editor. The specific features and settings vary slightly
by editor, so we recommend that you proceed to the
[documentation for your editor](#editors) below.
Also, the gopls documentation for each feature describes whether it is
supported in each client editor.
This documentation (https://go.dev/gopls) describes the most recent release of gopls.
To preview documentation for the release under development, visit https://tip.golang.org/gopls.
## Features
Gopls supports a wide range of standard LSP features for navigation,
completion, diagnostics, analysis, and refactoring, and a number of
additional features not found in other language servers.
See the [Index of features](features/) for complete
documentation on what Gopls can do for you.
## Editors
To get started with `gopls`, install an LSP plugin in your editor of choice.
* [Acme](https://github.com/fhs/acme-lsp/blob/master/README.md)
* [Atom](https://github.com/MordFustang21/ide-gopls/blob/master/README.md)
* [Emacs](editor/emacs.md)
* [Helix](editor/helix.md)
* [Lapce](https://github.com/lapce-community/lapce-go/blob/master/README.md)
* [Sublime Text](editor/sublime.md)
* [VS Code](https://github.com/golang/vscode-go/blob/master/README.md)
* [Vim or Neovim](editor/vim.md)
* [Zed](editor/zed.md)
If you use `gopls` with an editor that is not on this list, please send us a CL
[updating this documentation](contributing.md).
## Installation
To install the latest stable release of `gopls`, run the following command:
```sh
go install golang.org/x/tools/gopls@latest
```
Some editors, such as VS Code, will handle this step for you, and
ensure that Gopls is updated when a new stable version is released.
After updating, you may need to restart running Gopls processes to
observe the effect. Each client has its own way to restart the server.
(On a UNIX machine, you can use the command `killall gopls`.)
Learn more in the
[advanced installation instructions](advanced.md#installing-unreleased-versions).
## Releases
Gopls [releases](release/) follow [semantic versioning](http://semver.org), with
major changes and new features introduced only in new minor versions
(i.e. versions of the form `v*.N.0` for some N). Subsequent patch
releases contain only cherry-picked fixes or superficial updates.
In order to align with the
[Go release timeline](https://github.com/golang/go/wiki/Go-Release-Cycle#timeline),
we aim to release a new minor version of Gopls approximately every three
months, with patch releases approximately every month, according to the
following table:
| Month | Version(s) |
| ---- | ------- |
| Jan | `v*..0` |
| Jan-Mar | `v*..*` |
| Apr | `v*..0` |
| Apr-Jun | `v*..*` |
| Jul | `v*..0` |
| Jul-Sep | `v*..*` |
| Oct | `v*..0` |
| Oct-Dec | `v*..*` |
For more background on this policy, see https://go.dev/issue/55267.
## Setting up your workspace
`gopls` supports both Go module, multi-module and GOPATH modes. See the
[workspace documentation](workspace.md) for information on supported
workspace layouts.
## Configuration
You can configure `gopls` to change your editor experience or view additional
debugging information. Configuration options will be made available by your
editor, so see your [editor's instructions](#editors) for specific details. A
full list of `gopls` settings can be found in the [settings documentation](settings.md).
### Environment variables
`gopls` inherits your editor's environment, so be aware of any environment
variables you configure. Some editors, such as VS Code, allow users to
selectively override the values of some environment variables.
## Support policy
Gopls is maintained by engineers on the
[Go tools team](https://github.com/orgs/golang/teams/tools-team/members),
who actively monitor the
[Go](https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+label%3Agopls)
and
[VS Code Go](https://github.com/golang/vscode-go/issues) issue trackers.
### Supported Go versions
`gopls` follows the
[Go Release Policy](https://go.dev/doc/devel/release#policy), meaning
that it officially supports only the two most recent major Go releases.
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.
Starting with the release of Go 1.23.0 and gopls@v0.17.0 in August 2024, we
will only support the most recent Go version as the _gopls build go version_.
However, due to the [forward compatibility](https://go.dev/blog/toolchain)
support added in Go 1.21, as long as Go 1.21 or later are used to install
gopls, any necessary toolchain upgrade will be handled automatically, just like
any other dependency.
Additionally, starting with gopls@v0.17.0, the _go command version_ will narrow
from 4 versions to 3. This is more consistent with the Go Release Policy.
Gopls supports **all** Go versions as its _language version_, by providing
compiler errors based on the language version and filtering available standard
library symbols based on the standard library APIs available at that Go
version.
Maintaining support for building gopls with legacy versions of Go caused
[significant friction](https://go.dev/issue/50825) for gopls maintainers and
held back other improvements. If you are unable to install a supported version
of Go on your system, you can still install an older version of gopls. The
following table shows the final gopls version that supports a given Go version.
Go releases more recent than those in the table can be used with any version of
gopls.
| Go Version | Final gopls version with support (without warnings) |
| ----------- | --------------------------------------------------- |
| Go 1.12 | [gopls@v0.7.5](https://github.com/golang/tools/releases/tag/gopls%2Fv0.7.5) |
| Go 1.15 | [gopls@v0.9.5](https://github.com/golang/tools/releases/tag/gopls%2Fv0.9.5) |
| Go 1.17 | [gopls@v0.11.0](https://github.com/golang/tools/releases/tag/gopls%2Fv0.11.0) |
| Go 1.18 | [gopls@v0.14.2](https://github.com/golang/tools/releases/tag/gopls%2Fv0.14.2) |
| Go 1.20 | [gopls@v0.15.3](https://github.com/golang/tools/releases/tag/gopls%2Fv0.15.3) |
### Supported build systems
`gopls` currently only supports the `go` command, so if you are using
a different build system, `gopls` will not work well. Bazel is not officially
supported, but may be made to work with an appropriately configured
[go/packages driver](https://pkg.go.dev/golang.org/x/tools/go/packages#hdr-The_driver_protocol).
See [bazelbuild/rules_go#512](https://github.com/bazelbuild/rules_go/issues/512)
for more information.
You can follow [these instructions](https://github.com/bazelbuild/rules_go/wiki/Editor-setup)
to configure your `gopls` to work with Bazel.
### Troubleshooting
If you are having issues with `gopls`, please follow the steps described in the
[troubleshooting guide](troubleshooting.md).
## Additional information
* [Command-line interface](command-line.md)
* [Advanced topics](advanced.md)
* [Open issues](https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+label%3Agopls)
* [Contributing to `gopls`](contributing.md)
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/inlayHints.md
---
title: "Gopls: Inlay hints"
---
Inlay hints are helpful annotations that the editor can optionally
display in-line in the source code, such as the names of parameters in
a function call. This document describes the inlay hints available
from `gopls`.
## **assignVariableTypes**
`"assignVariableTypes"` controls inlay hints for variable types in assign statements:
```go
i/* int*/, j/* int*/ := 0, len(r)-1
```
**Disabled by default. Enable it by setting `"hints": {"assignVariableTypes": true}`.**
## **compositeLiteralFields**
`"compositeLiteralFields"` inlay hints for composite literal field names:
```go
{/*in: */"Hello, world", /*want: */"dlrow ,olleH"}
```
**Disabled by default. Enable it by setting `"hints": {"compositeLiteralFields": true}`.**
## **compositeLiteralTypes**
`"compositeLiteralTypes"` controls inlay hints for composite literal types:
```go
for _, c := range []struct {
in, want string
}{
/*struct{ in string; want string }*/{"Hello, world", "dlrow ,olleH"},
}
```
**Disabled by default. Enable it by setting `"hints": {"compositeLiteralTypes": true}`.**
## **constantValues**
`"constantValues"` controls inlay hints for constant values:
```go
const (
KindNone Kind = iota/* = 0*/
KindPrint/* = 1*/
KindPrintf/* = 2*/
KindErrorf/* = 3*/
)
```
**Disabled by default. Enable it by setting `"hints": {"constantValues": true}`.**
## **functionTypeParameters**
`"functionTypeParameters"` inlay hints for implicit type parameters on generic functions:
```go
myFoo/*[int, string]*/(1, "hello")
```
**Disabled by default. Enable it by setting `"hints": {"functionTypeParameters": true}`.**
## **ignoredError**
`"ignoredError"` inlay hints for implicitly discarded errors:
```go
f.Close() // ignore error
```
This check inserts an `// ignore error` hint following any
statement that is a function call whose error result is
implicitly ignored.
To suppress the hint, write an actual comment containing
"ignore error" following the call statement, or explictly
assign the result to a blank variable. A handful of common
functions such as `fmt.Println` are excluded from the
check.
**Disabled by default. Enable it by setting `"hints": {"ignoredError": true}`.**
## **parameterNames**
`"parameterNames"` controls inlay hints for parameter names:
```go
parseInt(/* str: */ "123", /* radix: */ 8)
```
**Disabled by default. Enable it by setting `"hints": {"parameterNames": true}`.**
## **rangeVariableTypes**
`"rangeVariableTypes"` controls inlay hints for variable types in range statements:
```go
for k/* int*/, v/* string*/ := range []string{} {
fmt.Println(k, v)
}
```
**Disabled by default. Enable it by setting `"hints": {"rangeVariableTypes": true}`.**
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/release/v0.16.0.md
---
title: "Gopls release v0.16.0"
---
```
go install golang.org/x/tools/gopls@v0.16.2
```
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](https://go.dev/blog/toolchain)
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](https://github.com/golang/tools/tree/master/gopls#support-policy)
for details. Please comment on golang/go#65917 if
you have concerns about this change.
## Configuration changes
- The experimental `allowImplicitNetworkAccess` setting is deprecated (but not
yet removed). Please comment on golang/go#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 the new language features of Go 1.23,
including
[range-over-func](https://go.dev/wiki/RangefuncExperiment) iterators
and support for the
[`godebug` directive](https://go.dev/ref/mod#go-mod-file-godebug)
in go.mod files.
### Integrated documentation viewer
Gopls now offers a "Browse documentation" code action that opens a
local web page displaying the generated documentation for Go packages
and symbols in a form similar to https://pkg.go.dev.
The package or symbol is chosen based on the current selection.
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.
As in `pkg.go.dev`, the heading for each symbol contains a link to the
source code of its declaration. In `pkg.go.dev`, these links would refer
to a source code page on a site such as GitHub or Google Code Search.
However, in gopls' internal viewer, clicking on one of these links will
cause your editor to navigate to the declaration.
(This feature requires that your LSP client honors the `showDocument` downcall.)
Editor support:
- VS Code: use the "Source action > Browse documentation for func fmt.Println" menu item.
Note: source links navigate the editor but don't yet raise the window yet.
Please upvote microsoft/vscode#208093 and microsoft/vscode#207634 (temporarily closed).
- Emacs: requires eglot v1.17. Use `M-x go-browse-doc` from github.com/dominikh/go-mode.el.
The `linksInHover` setting now supports a new value, `"gopls"`,
that causes documentation links in the Markdown output
of the Hover operation to link to gopls' internal doc viewer.
### 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
approximately the set of parameters that would be needed if the block
were extracted into its own function.
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.
Editor support:
- VS Code: use the `Source action > Browse free symbols` menu item.
- Emacs: requires eglot v1.17. Use `M-x go-browse-freesymbols` from github.com/dominikh/go-mode.el.
### Browse assembly
Gopls offers a third web-based code action, "Browse assembly for f",
which displays an assembly listing of the declaration of the function
f enclosing the selected code, plus any nested functions such as
function literals or deferred calls.
Gopls invokes the compiler to generate the report;
reloading the page updates the report.
The machine architecture is determined by the 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.
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.
Editor support:
- VS Code: use the "Source action > Browse assembly for f" menu item.
- Emacs: requires eglot v1.17. Use `M-x go-browse-assembly` from github.com/dominikh/go-mode.el.
### `unusedwrite` analyzer
The new
[unusedwrite](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/unusedwrite)
analyzer reports assignments, often to fields of structs, that have no
effect because, for example, the struct is never used again:
```go
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:
```go
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`](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/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.
Consider the go.mod file and Go file below.
The declaration of `var `alias refers to a type, `types.Alias`,
introduced in go1.22, but the file belongs to a module that requires
only go1.21, so the analyzer reports a diagnostic:
```
module example.com
go 1.21
```
```go
package p
import "go/types"
var alias types.Alias // types.Alias requires go1.22 or later (module is go1.21)
```
When an individual file is build-tagged for a release of Go other than
than module's version, the analyzer will apply appropriate checks for
the file's version.
### Two more vet analyzers
The [framepointer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/framepointer)
and [sigchanyzer](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/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
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:
In the struct above, alignment rules require each of the two boolean
fields (1 byte) to occupy a complete word (8 bytes), leading to (7 + 7) / (3 \* 8) = 58% waste.
Placing the two booleans together would save a word.
This information may be helpful when making space optimizations to
your data structures, or when reading assembly code.
Also, hovering over a reference to a field with a struct tag now also
display the tag:
### Hover and "Go to Definition" work on symbols in doc comments
Go 1.19 added support for [doc links](https://go.dev/doc/comment#links),
allowing the doc comment for one symbol to reference another.
Gopls' Hover and Definition operations now treat these links just
like identifiers, so hovering over one will display information about
the symbol:
Similarly, "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
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/release/v0.17.0.md
---
title: "Gopls release v0.17.0"
---
```
go install golang.org/x/tools/gopls@v0.17.0-pre.4
```
## New support policies
With this release, we are narrowing our official support window to align with
the [Go support policy](https://go.dev/doc/devel/release#policy). This will
reduce the considerable costs to us of testing against older Go versions,
allowing us to spend more time fixing bugs and adding features that benefit the
majority of gopls users who run recent versions of Go.
This narrowing is occurring in two dimensions: **build compatibility** refers to
the versions of the Go toolchain that can be used to build gopls, and **go
command compatibility** refers to the versions of the `go` command that can be
used by gopls to list information about packages and modules in your workspace.
### Build compatibility: the most recent major Go version
As described in the [v0.16.0 release
notes](https://github.com/golang/tools/releases/tag/gopls%2Fv0.16.0), building the
latest version of gopls will now require the latest major version of the Go
toolchain. Therefore this release (gopls@v0.17.0) must be built with Go 1.23.0
or later. Thanks to [automatic toolchain
upgrades](https://go.dev/blog/toolchain), if your system Go version is at least
Go 1.21.0 and you have `GOTOOLCHAIN=auto` set (the default), the `go` command
will automatically download the new Go toolchain as needed, similar to
upgrading a module dependency.
### Go command compatibility: the 2 most recent major Go versions
The gopls@v0.17.x releases will be the final versions of gopls to nominally
support integrating with more than the 2 most recent Go releases. In the past,
we implied "best effort" support for up to 4 versions, though in practice we
did not have resources to fix bugs that were present only with older Go
versions. With gopls@v0.17.0, we narrowed this best effort support to 3
versions, primarily because users need at least Go 1.21 to benefit from
automatic toolchain upgrades (see above).
Starting with gopls@v0.18.0, we will officially support integrating with only
the 2 most recent major versions of the `go` command. This is consistent with
the Go support policy. See golang/go#69321 (or [this
comment](https://github.com/golang/go/issues/69321#issuecomment-2344996677)
specifically) for details.
We won't prevent gopls from being used with older Go versions (just as we
don't disallow integration with arbitrary
[`go/packages`](https://pkg.go.dev/golang.org/x/tools/go/packages) drivers),
but we won't run integration tests against older Go versions, and won't fix
bugs that are only present when used with old Go versions.
## Configuration Changes
- The `fieldalignment` analyzer, previously disabled by default, has
been removed: it is redundant with the hover size/offset information
displayed by v0.16.0 and its diagnostics were confusing.
- The `undeclaredname` analyzer has been replaced with an ordinary code action.
- The kind (identifiers) of all of gopls' code actions have changed
to use more specific hierarchical names. For example, "Inline call"
has changed from `refactor.inline` to `refactor.inline.call`.
This allows clients to request particular code actions more precisely.
The user manual now includes the identifier in the documentation for each code action.
- The experimental `allowImplicitNetworkAccess` setting is removed, following
its deprecation in gopls@v0.16.0. See golang/go#66861 for details.
## New features
### Refactoring
This release contains a number of new features related to refactoring.
Additionally, it fixes [many
bugs](https://github.com/golang/go/issues?q=is%3Aissue+milestone%3Agopls%2Fv0.17.0+label%3ARefactoring+is%3Aclosed)
in existing refactoring operations, primarily related to **extract**, and **inline**.
These improvements move us toward a longer term goal of offering a more robust
and complete set of refactoring tools. We still have [much to
do](https://github.com/golang/go/issues?q=is%3Aissue+label%3Agopls+label%3ARefactoring+is%3Aopen+),
and this effort will continue into 2025.
#### Move parameter refactorings
Gopls now offers code actions to move function and method parameters left or
right in the function signature, updating all callers.
Unfortunately, there is no native LSP operation that provides a good user
interface for arbitrary "change signature" refactoring. We plan to build such
an interface within VS Code. In the short term, we have made it possible to
express more complicated parameter transformations by invoking 'rename' on the
'func' keyword. This user interface is a temporary stop-gap until a better
mechanism is available for LSP commands that enable client-side dialogs.
#### Extract declarations to new file
Gopls now offers another code action,
"Extract declarations to new file" (`refactor.extract.toNewFile`),
which moves selected code sections to a newly created file within the
same package. The created filename is chosen as the first {function, type,
const, var} name encountered. In addition, import declarations are added or
removed as needed.
The user can invoke this code action by selecting a function name, the keywords
`func`, `const`, `var`, `type`, or by placing the caret on them without selecting,
or by selecting a whole declaration or multiple declarations.
In order to avoid ambiguity and surprise about what to extract, some kinds
of partial selection of a declaration cannot invoke this code action.
#### Extract constant
When the selection is a constant expression, gopls now offers "Extract
constant" instead of "Extract variable", and generates a `const`
declaration instead of a local variable.
Also, extraction of a constant or variable now works at top-level,
outside of any function.
#### Generate missing method from function call
When you attempt to call a method on a type that lacks that method, the
compiler will report an error like “type T has no field or method f”. Gopls now
offers a new code action, “Declare missing method of T.f”, where T is the
concrete type and f is the undefined method. The stub method's signature is
inferred from the context of the call.
#### Generate a test for a function or method
If the selected chunk of code is part of a function or method declaration F,
gopls will offer the "Add test for F" code action, which adds a new test for the
selected function in the corresponding `_test.go` file. The generated test takes
into account its signature, including input parameters and results.
Since this feature is implemented by the server (gopls), it is compatible with
all LSP-compliant editors. VS Code users may continue to use the client-side
`Go: Generate Unit Tests For file/function/package` command, which runs the
[gotests](https://github.com/cweill/gotests) tool.
### Initial support for pull diagnostics
When initialized with the option `"pullDiagnostics": true`, gopls will advertise support for the
`textDocument.diagnostic`
[client capability](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_pullDiagnostics),
which allows editors to request diagnostics directly from gopls using a
`textDocument/diagnostic` request, rather than wait for a
`textDocument/publishDiagnostics` notification. This feature is off by default
until the feature set of pull diagnostics is comparable to push diagnostics.
### Hover improvements
The `textDocument/hover` response has slightly tweaked markdown rendering, and
includes the following additional information:
- Hovering over a standard library symbol now displays information about the
first Go release containing the symbol. For example, hovering over
`errors.As` shows "Added in go1.13".
- Hovering over the package name in a package declaration includes additional
package metadata.
### Semantic token modifiers of top-level constructor of types
The semantic tokens response now includes additional modifiers for the top-level
constructor of the type of each symbol:
`interface`, `struct`, `signature`, `pointer`, `array`, `map`, `slice`, `chan`, `string`, `number`, `bool`, and `invalid`.
Editors may use this for syntax coloring.
### SignatureHelp for ident and values.
Now, function signature help can be used on any identifier with a function
signature, not just within the parentheses of a function being called.
### Jump to assembly definition
A Definition query on a reference to a function jumps to the
function's Go `func` declaration. If the function is implemented in C
or assembly, the function has no body. Executing a second Definition
query (while already at the Go declaration) will navigate you to the
assembly implementation.
### `yield` analyzer
The new `yield` analyzer detects mistakes using the `yield` function
in a Go 1.23 iterator, such as failure to check its boolean result and
break out of a loop.
### `waitgroup` analyzer
The new `waitgroup` analyzer detects calls to the `Add` method of
`sync.WaitGroup` that are (mistakenly) made within the new goroutine,
causing `Add` to race with `Wait`.
(This check is equivalent to
[staticcheck's SA2000](https://staticcheck.dev/docs/checks#SA2000),
but is enabled by default.)
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/release/v0.18.0.md
---
title: "Gopls release v0.18.0"
---
## Configuration Changes
- The experimental `Structured` value for the `hoverKind` option is no longer
supported.
- The `gc_details` code lens has been deleted. (It was previously disabled by
default.) This functionality is now available through the
`toggleCompilerOptDetails` code action (documented below), as code
actions are better supported than code lenses across a range of clients.
VS Code's special "Go: Toggle GC details" command continues to work.
- The experimental `semanticTokenTypes` and `semanticTokenModifiers` options
allow selectively disabling certain types of tokens or token modifiers in
`textDocument/semanticTokens` responses.
These options supersede the `noSemanticString` and `noSemanticTokenNumber`
options, which are now deprecated. Users can instead set
`"semanticTokenTypes": {"string": false, "number": false}` to achieve the
same result. For now, gopls still honors `noSemanticTokenString` and
`noSemanticToken`, but will stop supporting them in a future release.
- The new `workspaceFiles` option allows configuring glob patterns matching
files that define the logical build of the workspace. This option is only
needed in environments that use a custom golang.org/x/tools/go/packages
driver.
## New features
### "{Show,Hide} compiler optimization details" code action
This code action, accessible through the "Source Action" menu in VS
Code, toggles a per-directory flag that causes Go compiler optimization
details to be reported as diagnostics. For example, it indicates which
variables escape to the heap, and which array accesses require bounds
checks.
TODO: add links to the complete manual for each item.
### New `modernize` analyzer
Gopls now reports when code could be simplified or clarified by
using more modern features of Go, and provides a quick fix to apply
the change.
For example, a conditional assignment using an if/else statement may
be replaced by a call to the `min` or `max` built-in functions added
in Go 1.18.
Use this command to apply modernization fixes en masse:
```
$ go run golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest -fix ./...
```
### New `unusedfunc` analyzer
Gopls now reports unused functions and methods, giving you near
real-time feedback about dead code that may be safely deleted.
Because the analysis is local to each package, only unexported
functions and methods are candidates.
(For a more precise analysis that may report unused exported
functions too, use the `golang.org/x/tools/cmd/deadcode` command.)
### New `hostport` analyzer
With the growing use of IPv6, forming a "host:port" string using
`fmt.Sprintf("%s:%d")` is no longer appropriate because host names may
contain colons. Gopls now reports places where a string constructed in
this fashion (or with `%s` for the port) is passed to `net.Dial` or a
related function, and offers a fix to use `net.JoinHostPort`
instead.
### Other analyzer changes
- The `unusedvariable` quickfix is now on by default.
- The `unusedparams` analyzer no longer reports finding for generated files.
### New `gofix` analyzer
Gopls now reports when a function call or a use of a constant should be inlined.
These diagnostics and the associated code actions are triggered by "//go:fix inline"
directives at the function and constant definitions.
(See [the go:fix proposal](https://go.dev/issue/32816).)
For example, consider a package `intmath` with a function `Square(int) int`.
Later the more general `Pow(int, int) int` is introduced, and `Square` is deprecated
in favor of calling `Pow` with a second argument of 2. The author of `intmath`
can write this:
```
//go:fix inline
func Square(x int) int { return Pow(x, 2) }
```
If gopls sees a call to `intmath.Square` in your code, it will suggest inlining
it, and will offer a code action to do so.
The same feature works for constants.
With a constant definition like this:
```
//go:fix inline
const Ptr = Pointer
```
gopls will suggest replacing `Ptr` in your code with `Pointer`.
Use this command to apply such fixes en masse:
```
$ go run golang.org/x/tools/go/analysis/passes/inline/cmd/inline@latest -fix ./...
```
### "Implementations" supports generics
At long last, the "Go to Implementations" feature now fully supports
generic types and functions (#59224).
For example, invoking the feature on the interface method `Stack.Push`
below will report the concrete method `C[T].Push`, and vice versa.
```go
package p
type Stack[T any] interface {
Push(T) error
Pop() (T, bool)
}
type C[T any] struct{}
func (C[T]) Push(t T) error { ... }
func (C[T]) Pop() (T, bool) { ... }
var _ Stack[int] = C[int]{}
```
### Extract all occurrences of the same expression under selection
When you have multiple instances of the same expression in a function,
you can use this code action to extract it into a variable.
All occurrences of the expression will be replaced with a reference to the new variable.
### Improvements to "Definition"
The Definition query now supports additional locations:
- When invoked on a return statement, it reports the location
of the function's result variables.
- When invoked on a break, goto, or continue statement, it reports
the location of the label, the closing brace of the relevant
block statement, or the start of the relevant loop, respectively.
### Improvements to "Hover"
When invoked on a return statement, hover reports the types of
the function's result variables.
### UX improvements to format strings
#### "DocumentHighlight"
When your cursor is inside a printf-like function, gopls now highlights the relationship between
formatting verbs and arguments as visual cues to differentiate how operands are used in the format string.
```go
fmt.Printf("Hello %s, you scored %d", name, score)
```
If the cursor is either on `%s` or `name`, gopls will highlight `%s` as a write operation,
and `name` as a read operation.
#### "SemanticHighlight"
Similar to the improvements to DocumentHighlight, gopls also reports formatting verbs
as "format" modifier for token type "string" to better distinguish them with other parts of the format string.
```go
fmt.Printf("Hello %s, you scored %d", name, score)
```
`%s` and `%d` will have token type "string" and modifier "format".
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/release/v0.19.0.md
---
title: "Gopls release v0.19.0"
---
## Configuration Changes
- The `gopls check` subcommand now accepts a `-severity` flag to set a minimum
severity for the diagnostics it reports. By default, the minimum severity
is "warning", so `gopls check` may report fewer diagnostics than before. Set
`-severity=hint` to reproduce the previous behavior.
## Navigation features
### "Implementations" supports signature types (within same package)
The Implementations query reports the correspondence between abstract
and concrete types and their methods based on their method sets.
Now, it also reports the correspondence between function types,
dynamic function calls, and function definitions, based on their signatures.
To use it, invoke an Implementations query on the `func` token of the
definition of a named function, named method, or function literal.
Gopls reports the set of function signature types that abstract this
function, and the set of dynamic calls through values of such types.
Conversely, an Implementations query on the `func` token of a
signature type, or on the `(` paren of a dynamic function call,
reports the set of concrete functions that the signature abstracts
or that the call dispatches to.
Since a type may be both a function type and a named type with methods
(for example, `http.HandlerFunc`), it may participate in both kinds of
Implements queries (method-sets and function signatures).
Queries using method-sets should be invoked on the type or method name,
and queries using signatures should be invoked on a `func` or `(` token.
Only the local (same-package) algorithm is currently supported.
(https://go.dev/issue/56572 tracks the global algorithm.)
### "Go to Implementation" reports interface-to-interface relations
The "Go to Implementation" operation now reports relationships between
interfaces. Gopls now uses the concreteness of the query type to
determine whether a query is "downwards" (from an interface to the
types that implement it) or "upwards" (from a concrete type to the
interfaces to which it may be assigned). So, for example:
- `implementation(io.Reader)` subinterfaces such as `io.ReadCloser`,
and concrete implementations such as `*os.File`.
- `implementation(os.File)` includes only interfaces, such as
`io.Reader` and `io.ReadCloser`.
To request an "upwards" query starting from an interface, for example
to find the superinterfaces of `io.ReadCloser`, use the Type Hierarchy
feature described below.
(See https://github.com/microsoft/language-server-protocol/issues/2037.)
### Support for Type Hierarchy
Gopls now implements the three LSP methods related to the Type
Hierarchy viewer: `textDocument/prepareTypeHierarchy`,
`typeHierarchy/supertypes`, `typeHierarchy/subtypes`.
In VS Code, select "Show Type Hierarchy" from the context menu
to see a tree widget displaying all the supertypes or subtypes
of the selected named type.
## Editing features
### Completion: auto-complete package clause for new Go files
Gopls now automatically adds the appropriate `package` clause to newly created Go files,
so that you can immediately get started writing the interesting part.
It requires client support for `workspace/didCreateFiles`
### New GOMODCACHE index for faster Organize Imports and unimported completions
By default, gopls now builds and maintains a persistent index of
packages in the module cache (GOMODCACHE). The operations of Organize
Imports and completion of symbols from unimported pacakges are an
order of magnitude faster.
To revert to the old behavior, set the `importsSource` option (whose
new default is `"gopls"`) to `"goimports"`. Users who don't want the
module cache used at all for imports or completions can change the
option to "off".
## Analysis features
### Most `staticcheck` analyzers are enabled by default
Slightly more than half of the analyzers in the
[Staticcheck](https://staticcheck.dev/docs/checks) suite are now
enabled by default. This subset has been chosen for precision and
efficiency.
Previously, Staticcheck analyzers (all of them) would be run only if
the experimental `staticcheck` boolean option was set to `true`. This
value continues to enable the complete set, and a value of `false`
continues to disable the complete set. Leaving the option unspecified
enables the preferred subset of analyzers.
Staticcheck analyzers, like all other analyzers, can be explicitly
enabled or disabled using the `analyzers` configuration setting; this
setting now takes precedence over the `staticcheck` setting, so,
regardless of what value of `staticcheck` you use (true/false/unset),
you can make adjustments to your preferred set of analyzers.
### `recursiveiter`: "inefficient recursive iterator"
A common pitfall when writing a function that returns an iterator
(`iter.Seq`) for a recursive data type is to recursively call the
function from its own implementation, leading to a stack of nested
coroutines, which is inefficient.
The new `recursiveiter` analyzer detects such mistakes; see
[its documentation](https://golang.org/x/tools/gopls/internal/analysis/recursiveiter)
for details, including tips on how to define simple and efficient
recursive iterators.
### `maprange`: "inefficient range over maps.Keys/Values"
The new `maprange` analyzer detects redundant calls to `maps.Keys` or
`maps.Values` as the operand of a range loop; maps can of course be
ranged over directly. See
[its documentation](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/maprange)
for details).
## Code transformation features
### Rename method receivers
The Rename operation, when applied to the declaration of a method
receiver, now also attempts to rename the receivers of all other
methods associated with the same named type. Each other receiver that
cannot be fully renamed is quietly skipped.
Renaming a _use_ of a method receiver continues to affect only that
variable.
```go
type Counter struct { x int }
Rename here to affect only this method
↓
func (c *Counter) Inc() { c.x++ }
func (c *Counter) Dec() { c.x++ }
↑
Rename here to affect all methods
```
### "Eliminate dot import" code action
This code action, available on a dotted import, will offer to replace
the import with a regular one and qualify each use of the package
with its name.
### Add/remove tags from struct fields
Gopls now provides two new code actions, available on an entire struct
or some of its fields, that allow you to add and remove struct tags.
It adds only 'json' tags with a snakecase naming format, or clears all
tags within the selection.
Add tags example:
```go
type Info struct {
LinkTarget string -> LinkTarget string `json:"link_target"`
...
}
```
### Inline local variable
The new `refactor.inline.variable` code action replaces a reference to
a local variable by that variable's initializer expression. For
example, when applied to `s` in `println(s)`:
```go
func f(x int) {
s := fmt.Sprintf("+%d", x)
println(s)
}
```
it transforms the code to:
```go
func f(x int) {
s := fmt.Sprintf("+%d", x)
println(fmt.Sprintf("+%d", x))
}
```
Only a single reference is replaced; issue https://go.dev/issue/70085
tracks the feature to "inline all" uses of the variable and eliminate
it.
## Thank you to our contributors!
[@acehinnnqru](https://github.com/acehinnnqru)
[@adonovan](https://github.com/adonovan)
[@albfan](https://github.com/albfan)
[@aarzilli](https://github.com/aarzilli)
[@ashurbekovz](https://github.com/ashurbekovz)
[@cuonglm](https://github.com/cuonglm)
[@dmitshur](https://github.com/dmitshur)
[@neild](https://github.com/neild)
[@egonelbre](https://github.com/egonelbre)
[@shashank](https://github.com/shashank)
[priyadarshi](https://github.compriyadarshi)
[@firelizzard18](https://github.com/firelizzard18)
[@gopherbot](https://github.com/gopherbot)
[@h9jiang](https://github.com/h9jiang)
[@cuishuang](https://github.com/cuishuang)
[@jakebailey](https://github.com/jakebailey)
[@jba](https://github.com/jba)
[@madelinekalil](https://github.com/madelinekalil)
[@karamaru](https://github.com/karamaru)
[alpha](https://github.comalpha)
[@danztran](https://github.com/danztran)
[@nsrip](https://github.com/nsrip)
[dd](https://github.comdd)
[@pjweinb](https://github.com/pjweinb)
[@findleyr](https://github.com/findleyr)
[@samthanawalla](https://github.com/samthanawalla)
[@seankhliao](https://github.com/seankhliao)
[@tklauser](https://github.com/tklauser)
[@vikblom](https://github.com/vikblom)
[@kwjw](https://github.com/kwjw)
[@xieyuschen](https://github.com/xieyuschen)
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/release/v0.20.0.md
---
title: "Gopls release v0.20.0"
---
This release contains a new experimental Model Context Protocol (MCP)
server for gopls, which may be used to integrate a subset of gopls'
features in AI-assisted environments.
Gopls' documentation is now available on the Go project's website at
https://go.dev/gopls. (This link reflects the latest gopls release;
use https://tip.golang.org/gopls to see docs for the latest commit.)
Unlike Markdown files in GitHub, these pages are crawled by Google's
web search index.
## Configuration changes
This release enables by default the new persistent index of packages
in the module cache. This was first attempted in [v0.19](./v0.19.0.md) but reverted
due to problems that have since been fixed.
## Web-based features
### "Split package" tool
The `source.splitPackage` code action opens a web-based tool that
helps you split a package into two or more components whose
dependencies are acyclic.
To use it, name a set of components, assign each declaration to a
component, then visualize the dependencies among the components
(including whether they form a cycle).
Refresh the page each time you edit your code to see the latest
information.

The tool makes it easy to iterate over potential decompositions
until you find one you are happy with. A future version of
the tool will automate the code transformation, but for now
you must do that step by hand.
## Editing features
### Model Context Protocol server
Gopls now includes an experimental built-in server for the Model Context
Protocol (MCP), allowing it to expose a subset of its functionality to
AI assistants in the form of MCP tools.
See the [documentation](../features/mcp.md) for more information.
**Caveats:** This is a brand new mode of operation for gopls, and so we're
still experimenting with the best set of tools and instructions to provide.
Please let us know how well it works for you. Also, please be aware that
allowing LLMs to execute operations in your workspace entails additional
security considerations, as discussed in the documentation above.
## Analysis features
### `ignoredError` inlay hint
The new `ignoredError` inlay hint helps catch mistakenly discarded
errors. It inserts an `// ignore error` hint following any statement
that is a function call whose error result is implicitly ignored. For
example, this code:
```go
f.Close()
```
will appear as:
```go
f.Close() // ignore error
```
To suppress the hint, write an actual comment containing `ignore
error` following the call statement, or explictly assign the result
to a blank `_` variable. A handful of common functions such as
`fmt.Println` are excluded from the check.
Enable it using this configuration: `{"hints": {"ignoredError": true}}`.
### `unusedfunc` reports unused `type`, `var`, and `const` declarations too
The
[unusedfunc](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedfunc/)
analyzer now reports any unexported types, variables, and constants
that are unreferenced within their declaring package.
(The problem of unreferenced exported symbols can't be expressed in
the analysis framework since it depends on the entire workspace.)
## Code transformation features
The Rename operation now allows you to rename an embedded field, such
as T in `struct{ T }`, so long as the operation is requested at the
field declaration (T). Both the field and its type will be renamed.
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/release/v0.21.0.md
---
title: "Gopls release v0.21.0 (expected Dec 2025)"
---
## Configuration changes
- The new `newGoFileHeader` option allows toggling automatic insertion of the copyright comment
and package declaration in a newly created Go file.
- The default value of the `codelenses` setting now includes
`run_govulncheck: true`, causing gopls to offer a "Run govulncheck"
command associated with the `module` declaration in a go.mod file.
- The experimental `vulncheck` setting now supports the enum value
`"Prompt"`, meaning that vulncheck can be triggered via a prompt;
this is now the default.
- The new, experimental `renameMovesSubpackages` setting 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:
```go
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
//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 `minmax` modernizer now removes user-defined min/max functions when they are redundant.
- The `stringscutprefix` modernizer now handles `strings.CutSuffix` too.
- The `yield` and `nilness` analyzers handle control-flow booleans more precisely.
- The `printf` analyzer now checks calls to local anonymous printf-wrapper functions too.
- The `staticcheck` suite 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`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_prepareRename) operation.
### Renaming from a doc link
The Rename operation now treats [doc links](https://tip.golang.org/doc/comment#doclinks)
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
https://github.com/golang/go/milestone/399?closed=1
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/release/v0.22.0.md
---
title: "Gopls release v0.22.0 (forthcoming)"
---
## Configuration changes
## Navigation features
- Asking for references while hovering over the name of a required module in a `go.mod` file
will show all the imports of that module in the main module (the go.mod's module).
## Web-based features
## Editing features
## Analysis features
### `foo` analyzer
Description
## Code transformation features
### $feature
https://go.dev/issue#xxxxx
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/settings.md
---
title: "Gopls: Settings"
---
This document describes gopls' configuration settings.
Gopls settings are defined by a JSON object whose valid fields are
described below. These fields are gopls-specific, and generic LSP
clients have no knowledge of them.
Different clients present configuration settings in their user
interfaces in a wide variety of ways.
For example, some expect the user to edit the raw JSON object while
others use a data structure in the editor's configuration language;
still others (such as VS Code) have a graphical configuration system.
Be sure to consult the documentation for how to express configuration
settings in your client.
Some clients also permit settings to be configured differently for
each workspace folder.
Any settings that are experimental or for debugging purposes are
marked as such.
* [Build](#build)
* [Formatting](#formatting)
* [UI](#ui)
* [Completion](#completion)
* [Diagnostic](#diagnostic)
* [Documentation](#documentation)
* [Inlayhint](#inlayhint)
* [Navigation](#navigation)
## Build
### `buildFlags []string`
buildFlags is the set of flags passed on to the build system when invoked.
It is applied to queries like `go list`, which is used when discovering files.
The most common use is to set `-tags`.
Default: `[]`.
### `env map[string]string`
env adds environment variables to external commands run by `gopls`, most notably `go list`.
Default: `{}`.
### `directoryFilters []string`
directoryFilters can be used to exclude unwanted directories from the
workspace. By default, all directories are included. Filters are an
operator, `+` to include and `-` to exclude, followed by a path prefix
relative to the workspace folder. They are evaluated in order, and
the last filter that applies to a path controls whether it is included.
The path prefix can be empty, so an initial `-` excludes everything.
DirectoryFilters also supports the `**` operator to match 0 or more directories.
Examples:
Exclude node_modules at current depth: `-node_modules`
Exclude node_modules at any depth: `-**/node_modules`
Include only project_a: `-` (exclude everything), `+project_a`
Include only project_a, but not node_modules inside it: `-`, `+project_a`, `-project_a/node_modules`
Default: `["-**/node_modules"]`.
### `templateExtensions []string`
templateExtensions gives the extensions of file names that are treated
as template files. (The extension
is the part of the file name after the final dot.)
Default: `[]`.
### `memoryMode string`
**This setting is experimental and may be deleted.**
obsolete, no effect
Default: `""`.
### `expandWorkspaceToModule bool`
**This setting is experimental and may be deleted.**
expandWorkspaceToModule determines which packages are considered
"workspace packages" when the workspace is using modules.
Workspace packages affect the scope of workspace-wide operations. Notably,
gopls diagnoses all packages considered to be part of the workspace after
every keystroke, so by setting "ExpandWorkspaceToModule" to false, and
opening a nested workspace directory, you can reduce the amount of work
gopls has to do to keep your workspace up to date.
Default: `true`.
### `standaloneTags []string`
standaloneTags specifies a set of build constraints that identify
individual Go source files that make up the entire main package of an
executable.
A common example of standalone main files is the convention of using the
directive `//go:build ignore` to denote files that are not intended to be
included in any package, for example because they are invoked directly by
the developer using `go run`.
Gopls considers a file to be a standalone main file if and only if it has
package name "main" and has a build directive of the exact form
"//go:build tag" or "// +build tag", where tag is among the list of tags
configured by this setting. Notably, if the build constraint is more
complicated than a simple tag (such as the composite constraint
`//go:build tag && go1.18`), the file is not considered to be a standalone
main file.
This setting is only supported when gopls is built with Go 1.16 or later.
Default: `["ignore"]`.
### `workspaceFiles []string`
workspaceFiles configures the set of globs that match files defining the
logical build of the current workspace. Any on-disk changes to any files
matching a glob specified here will trigger a reload of the workspace.
This setting need only be customized in environments with a custom
GOPACKAGESDRIVER.
Default: `[]`.
## Formatting
### `local string`
local is the equivalent of the `goimports -local` flag, which puts
imports beginning with this string after third-party packages. It should
be the prefix of the import path whose imports should be grouped
separately.
It is used when tidying imports (during an LSP Organize
Imports request) or when inserting new ones (for example,
during completion); an LSP Formatting request merely sorts the
existing imports.
Default: `""`.
### `gofumpt bool`
gofumpt indicates if we should run gofumpt formatting.
Default: `false`.
## UI
### `codelenses map[enum]bool`
codelenses overrides the enabled/disabled state of each of gopls'
sources of [Code Lenses](codelenses.md).
Example Usage:
```json5
"gopls": {
...
"codelenses": {
"generate": false, // Don't show the `go generate` lens.
}
...
}
```
Default: `{"generate":true,"regenerate_cgo":true,"run_govulncheck":true,"tidy":true,"upgrade_dependency":true,"vendor":true}`.
### `semanticTokens bool`
**This setting is experimental and may be deleted.**
semanticTokens controls whether the LSP server will send
semantic tokens to the client.
Default: `false`.
### `noSemanticString bool`
**This setting is experimental and may be deleted.**
noSemanticString turns off the sending of the semantic token 'string'
Deprecated: Use SemanticTokenTypes["string"] = false instead. See
golang/vscode-go#3632
Default: `false`.
### `noSemanticNumber bool`
**This setting is experimental and may be deleted.**
noSemanticNumber turns off the sending of the semantic token 'number'
Deprecated: Use SemanticTokenTypes["number"] = false instead. See
golang/vscode-go#3632.
Default: `false`.
### `semanticTokenTypes map[string]bool`
**This setting is experimental and may be deleted.**
semanticTokenTypes configures the semantic token types. It allows
disabling types by setting each value to false.
By default, all types are enabled.
Default: `{}`.
### `semanticTokenModifiers map[string]bool`
**This setting is experimental and may be deleted.**
semanticTokenModifiers configures the semantic token modifiers. It allows
disabling modifiers by setting each value to false.
By default, all modifiers are enabled.
Default: `{}`.
### `newGoFileHeader bool`
newGoFileHeader enables automatic insertion of the copyright comment
and package declaration in a newly created Go file.
Default: `true`.
### `renameMovesSubpackages bool`
**This setting is experimental and may be deleted.**
renameMovesSubpackages enables Rename operations on packages to
move subdirectories of the target package.
Default: `false`.
## Completion
### `usePlaceholders bool`
placeholders enables placeholders for function parameters or struct
fields in completion responses.
Default: `false`.
### `completionBudget time.Duration`
**This setting is for debugging purposes only.**
completionBudget is the soft latency goal for completion requests. Most
requests finish in a couple milliseconds, but in some cases deep
completions can take much longer. As we use up our budget we
dynamically reduce the search scope to ensure we return timely
results. Zero means unlimited.
Default: `"100ms"`.
### `matcher enum`
**This is an advanced setting and should not be configured by most `gopls` users.**
matcher sets the algorithm that is used when calculating completion
candidates.
Must be one of:
* `"CaseInsensitive"`
* `"CaseSensitive"`
* `"Fuzzy"`
Default: `"Fuzzy"`.
### `experimentalPostfixCompletions bool`
**This setting is experimental and may be deleted.**
experimentalPostfixCompletions enables artificial method snippets
such as "someSlice.sort!".
Default: `true`.
### `completeFunctionCalls bool`
completeFunctionCalls enables function call completion.
When completing a statement, or when a function return type matches the
expected of the expression being completed, completion may suggest call
expressions (i.e. may include parentheses).
Default: `true`.
## Diagnostic
### `analyses map[string]bool`
analyses specify analyses that the user would like to enable or disable.
A map of the names of analysis passes that should be enabled/disabled.
A full list of analyzers that gopls uses can be found in
[analyzers.md](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md).
Example Usage:
```json5
...
"analyses": {
"unreachable": false, // Disable the unreachable analyzer.
"unusedvariable": true // Enable the unusedvariable analyzer.
}
...
```
Default: `{}`.
### `staticcheck bool`
**This setting is experimental and may be deleted.**
staticcheck configures the default set of analyses staticcheck.io.
These analyses are documented on
[Staticcheck's website](https://staticcheck.io/docs/checks/).
The "staticcheck" option has three values:
- false: disable all staticcheck analyzers
- true: enable all staticcheck analyzers
- unset: enable a subset of staticcheck analyzers
selected by gopls maintainers for runtime efficiency
and analytic precision.
Regardless of this setting, individual analyzers can be
selectively enabled or disabled using the `analyses` setting.
Default: `false`.
### `staticcheckProvided bool`
**This setting is experimental and may be deleted.**
Default: `false`.
### `annotations map[enum]bool`
annotations specifies the various kinds of compiler
optimization details that should be reported as diagnostics
when enabled for a package by the "Toggle compiler
optimization details" (`gopls.gc_details`) command.
(Some users care only about one kind of annotation in their
profiling efforts. More importantly, in large packages, the
number of annotations can sometimes overwhelm the user
interface and exceed the per-file diagnostic limit.)
TODO(adonovan): rename this field to CompilerOptDetail.
Each enum must be one of:
* `"bounds"` controls bounds checking diagnostics.
* `"escape"` controls diagnostics about escape choices.
* `"inline"` controls diagnostics about inlining choices.
* `"nil"` controls nil checks.
Default: `{"bounds":true,"escape":true,"inline":true,"nil":true}`.
### `vulncheck enum`
**This setting is experimental and may be deleted.**
vulncheck enables vulnerability scanning.
Must be one of:
* `"Imports"`: In Imports mode, `gopls` will report vulnerabilities that affect packages
directly and indirectly used by the analyzed main module.
* `"Off"`: Disable vulnerability analysis.
* `"Prompt"`: Vulncheck can be triggered via prompt.
Default: `"Prompt"`.
### `diagnosticsDelay time.Duration`
**This is an advanced setting and should not be configured by most `gopls` users.**
diagnosticsDelay controls the amount of time that gopls waits
after the most recent file modification before computing deep diagnostics.
Simple diagnostics (parsing and type-checking) are always run immediately
on recently modified packages.
This option must be set to a valid duration string, for example `"250ms"`.
Default: `"1s"`.
### `diagnosticsTrigger enum`
**This setting is experimental and may be deleted.**
diagnosticsTrigger controls when to run diagnostics.
Must be one of:
* `"Edit"`: Trigger diagnostics on file edit and save. (default)
* `"Save"`: Trigger diagnostics only on file save. Events like initial workspace load
or configuration change will still trigger diagnostics.
Default: `"Edit"`.
### `analysisProgressReporting bool`
analysisProgressReporting controls whether gopls sends progress
notifications when construction of its index of analysis facts is taking a
long time. Cancelling these notifications will cancel the indexing task,
though it will restart after the next change in the workspace.
When a package is opened for the first time and heavyweight analyses such as
staticcheck are enabled, it can take a while to construct the index of
analysis facts for all its dependencies. The index is cached in the
filesystem, so subsequent analysis should be faster.
Default: `true`.
## Documentation
### `hoverKind enum`
hoverKind controls the information that appears in the hover text.
SingleLine is intended for use only by authors of editor plugins.
Must be one of:
* `"FullDocumentation"`
* `"NoDocumentation"`
* `"SingleLine"`
* `"Structured"` is a misguided experimental setting that returns a JSON
hover format. This setting should not be used, as it will be removed in a
future release of gopls.
* `"SynopsisDocumentation"`
Default: `"FullDocumentation"`.
### `linkTarget string`
linkTarget is the base URL for links to Go package
documentation returned by LSP operations such as Hover and
DocumentLinks and in the CodeDescription field of each
Diagnostic.
It might be one of:
* `"godoc.org"`
* `"pkg.go.dev"`
If company chooses to use its own `godoc.org`, its address can be used as well.
Modules matching the GOPRIVATE environment variable will not have
documentation links in hover.
Default: `"pkg.go.dev"`.
### `linksInHover enum`
linksInHover controls the presence of documentation links in hover markdown.
Must be one of:
* false: do not show links
* true: show links to the `linkTarget` domain
* `"gopls"`: show links to gopls' internal documentation viewer
Default: `true`.
## Inlayhint
### `hints map[enum]bool`
**This setting is experimental and may be deleted.**
hints specify inlay hints that users want to see. A full list of hints
that gopls uses can be found in
[inlayHints.md](https://github.com/golang/tools/blob/master/gopls/doc/inlayHints.md).
Default: `{}`.
## Navigation
### `importShortcut enum`
importShortcut specifies whether import statements should link to
documentation or go to definitions.
Must be one of:
* `"Both"`
* `"Definition"`
* `"Link"`
Default: `"Both"`.
### `symbolMatcher enum`
**This is an advanced setting and should not be configured by most `gopls` users.**
symbolMatcher sets the algorithm that is used when finding workspace symbols.
Must be one of:
* `"CaseInsensitive"`
* `"CaseSensitive"`
* `"FastFuzzy"`
* `"Fuzzy"`
Default: `"FastFuzzy"`.
### `symbolStyle enum`
**This is an advanced setting and should not be configured by most `gopls` users.**
symbolStyle controls how symbols are qualified in symbol responses.
Example Usage:
```json5
"gopls": {
...
"symbolStyle": "Dynamic",
...
}
```
Must be one of:
* `"Dynamic"` uses whichever qualifier results in the highest scoring
match for the given symbol query. Here a "qualifier" is any "/" or "."
delimited suffix of the fully qualified symbol. i.e. "to/pkg.Foo.Field" or
just "Foo.Field".
* `"Full"` is fully qualified symbols, i.e.
"path/to/pkg.Foo.Field".
* `"Package"` is package qualified symbols i.e.
"pkg.Foo.Field".
Default: `"Dynamic"`.
### `symbolScope enum`
symbolScope controls which packages are searched for workspace/symbol
requests. When the scope is "workspace", gopls searches only workspace
packages. When the scope is "all", gopls searches all loaded packages,
including dependencies and the standard library.
Must be one of:
* `"all"` matches symbols in any loaded package, including
dependencies.
* `"workspace"` matches symbols in workspace packages only.
Default: `"all"`.
### `verboseOutput bool`
**This setting is for debugging purposes only.**
verboseOutput enables additional debug logging.
Default: `false`.
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/troubleshooting.md
---
title: "Gopls: Troubleshooting"
---
If you suspect that `gopls` is crashing or not working correctly, please follow the troubleshooting steps below.
If `gopls` is using too much memory, please follow the steps under [Memory usage](#debug-memory-usage).
## Steps
VS Code users should follow [their troubleshooting guide](https://github.com/golang/vscode-go/blob/master/docs/troubleshooting.md), which has more a more specific version of these instructions.
1. Verify that your project is in good shape by working with it outside of your editor. Running a command like `go build ./...` in the workspace directory will compile everything. For modules, `go mod tidy` is another good check, though it may modify your `go.mod`.
1. Check that your editor isn't showing any diagnostics that indicate a problem with your workspace. They may appear as diagnostics on a Go file's package declaration, diagnostics in a go.mod file, or as a status or progress message. Problems in the workspace configuration can cause many different symptoms. See the [workspace setup instructions](workspace.md) for help.
1. Make sure `gopls` is up to date by following the [installation instructions](index.md#installation), then [restarting gopls](#restart-gopls).
1. Optionally, [ask for help](#ask-for-help) on Gophers Slack.
1. Finally, [report the issue](#file-an-issue) to the `gopls` developers.
## Restart `gopls`
`gopls` has no persistent state, so restarting it will fix transient problems. This is good and bad: good, because you can keep working, and bad, because you won't be able to debug the issue until it recurs.
In most cases, closing all your open editors will guarantee that `gopls` is killed and restarted. If you don't want to do that, there may be an editor command you can use to restart only `gopls`. Note that some `vim` configurations keep the server alive for a while after the editor exits; you may need to explicitly kill `gopls` if you use `vim`.
## Ask for help
Gophers Slack has active editor-specific channels like [#emacs](https://gophers.slack.com/archives/C0HKHULEM), [#vim](https://gophers.slack.com/archives/C07GBR52P), and [#vscode](https://gophers.slack.com/archives/C2B4L99RS) that can help debug further. If you're confident the problem is with `gopls`, you can go straight to [#gopls](https://gophers.slack.com/archives/CJZH85XCZ). Invites are [available to everyone](https://invite.slack.golangbridge.org). Come prepared with a short description of the issue, and try to be available to answer questions for a while afterward.
## File an issue
We can't diagnose a problem from just a description. When filing an issue, please include as much as possible of the following information:
1. Your editor and any settings you have configured (for example, your VSCode `settings.json` file).
1. A sample program that reproduces the issue, if possible.
1. The output of `gopls version` on the command line.
1. A complete gopls log file from a session where the issue occurred. It should have a `go env for ` log line near the beginning. It's also helpful to tell us the timestamp the problem occurred, so we can find it the log. See the [instructions](#capture-logs) for information on how to capture gopls logs.
Your editor may have a command that fills out some of the necessary information, such as `:GoReportGitHubIssue` in `vim-go`. Otherwise, you can use `gopls bug` on the command line. If neither of those work you can start from scratch directly on the [Go issue tracker](https://github.com/golang/go/issues/new?title=x%2Ftools%2Fgopls%3A%20%3Cfill%20this%20in%3E).
## Capture logs
You may have to change your editor's configuration to pass a `-logfile` flag to gopls.
To increase the level of detail in your logs, start `gopls` with the `-rpc.trace` flag. To start a debug server that will allow you to see profiles and memory usage, start `gopls` with `serve --debug=localhost:6060`. You will then be able to view debug information by navigating to `localhost:6060`.
If you are unsure of how to pass a flag to `gopls` through your editor, please see the [documentation for your editor](index.md#editors).
## Debug memory usage
`gopls` automatically writes out memory debug information when your usage exceeds 1GB. This information can be found in your temporary directory with names like `gopls.1234-5GiB-withnames.zip`. On Windows, your temporary directory will be located at `%TMP%`, and on Unixes, it will be `$TMPDIR`, which is usually `/tmp`. Please [file an issue](#file-an-issue) with this memory debug information attached. If you are uncomfortable sharing the package names of your code, you can share the `-nonames` zip instead, but it's much less useful.
---
# Source: https://github.com/golang/tools/blob/master/gopls/doc/workspace.md
---
title: "Gopls: Setting up your workspace"
---
In the language server protocol, a "workspace" consists of a folder along with
per-folder configuration. Some LSP clients such as VS Code allow configuring
workspaces explicitly, while others do so automatically by looking for special
files defining a workspace root (such as a `.git` directory or `go.mod` file).
In order to function, gopls needs a defined scope in which language features
like references, rename, and implementation should operate. Put differently,
gopls needs to infer from the LSP workspace which `go build` invocations you
would use to build your workspace, including the working directory,
environment, and build flags.
In the past, it could be tricky to set up your workspace so that gopls would
infer the correct build information. It required opening the correct directory
or using a `go.work` file to tell gopls about the modules you're working on,
and configuring the correct operating system and architecture in advance.
When this didn't work as expected, gopls would often fail in mysterious
ways--the dreaded "No packages found" error.
Starting with gopls v0.15.0, workspace configuration is much simpler, and gopls
will typically work when you open a Go file anywhere in your workspace. If it
isn't working for you, or if you want to better understand how gopls models
your workspace, please read on.
## Workspace builds
Starting with gopls v0.15.0, gopls will guess the builds you are working on
based on the set of open files. When you open a file in a workspace folder,
gopls checks whether the file is contained in a module, `go.work` workspace, or
GOPATH directory, and configures the build accordingly. Additionally, if you
open a file that is constrained to a different operating system or
architecture, for example opening `foo_windows.go` when working on Linux, gopls
will create a scope with `GOOS` and `GOARCH` set to a value that matches the
file.
For example, suppose we had a repository with three modules: `moda`, `modb`,
and `modc`, and a `go.work` file using modules `moda` and `modb`. If we open
the files `moda/a.go`, `modb/b.go`, `moda/a_windows.go`, and `modc/c.go`, gopls
will automatically create three builds:

This allows gopls to _just work_ when you open a Go file, but it does come with
several caveats:
- It causes gopls to do more work, since it is now tracking three builds
instead of one. However, the recent
[scalability redesign](https://go.dev/blog/gopls-scalability)
allows much of this work to be avoided through efficient caching.
- For operations invoked from a given file, such as "References"
or "Implementations", gopls executes the operation in
_the default build for that file_. For example, finding references to
a symbol `S` from `foo_linux.go` will return references from the Linux build,
and finding references to the same symbol `S` from `foo_windows.go` will
return references from the Windows build. Gopls searches the default build
for the file, but it doesn't search all the other possible builds (even
though that would be nice) because it is liable to be too expensive.
Issues [#65757](https://go.dev/issue/65757) and
[#65755](https://go.dev/issue/65755) propose improvements to this behavior.
- When selecting a `GOOS/GOARCH` combination to match a build-constrained file,
gopls will choose the first matching combination from
[this list](https://cs.opensource.google/go/x/tools/+/master:gopls/internal/cache/port.go;l=30;drc=f872b3d6f05822d290bc7bdd29db090fd9d89f5c).
In some cases, that may be surprising.
- When working in a `GOOS/GOARCH` constrained file that does not match your
default toolchain, `CGO_ENABLED=0` is implicitly set, since a C toolchain for
that target is unlikely to be available. This means that gopls will not
work in files including `import "C"`. Issue
[#65758](https://go.dev/issue/65758) may lead to improvements in this
behavior.
- Gopls is currently unable to guess build flags that include arbitrary
user-defined build constraints, such as a file with the build directive
`//go:build mytag`. Issue [#65089](https://go.dev/issue/65089) proposes
a heuristic by which gopls could handle this automatically.
Please provide feedback on this behavior by upvoting or commenting the issues
mentioned above, or opening a [new issue](https://go.dev/issue/new) for other
improvements you'd like to see.
## When to use a `go.work` file for development
Starting with Go 1.18, the `go` command has built-in support for multi-module
workspaces specified by [`go.work`](https://go.dev/ref/mod#workspaces) files.
Gopls will recognize these files if they are present in your workspace.
Use a `go.work` file when:
- you want to work on multiple modules simultaneously in a single logical
build, for example if you want changes to one module to be reflected in
another.
- you want to improve gopls' memory usage or performance by reducing the number
of builds it must track.
- you want gopls to know which modules you are working on in a multi-module
workspace, without opening any files. For example, it may be convenient to use
`workspace/symbol` queries before any files are open.
- you are using gopls v0.14.2 or earlier, and want to work on multiple
modules.
For example, suppose this repo is checked out into the `$WORK/tools` directory,
and [`x/mod`](https://pkg.go.dev/golang.org/x/mod) is checked out into
`$WORK/mod`, and you are working on a new `x/mod` API for editing `go.mod`
files that you want to simultaneously integrate into gopls.
You can work on both `golang.org/x/tools/gopls` and `golang.org/x/mod`
simultaneously by creating a `go.work` file:
```sh
cd $WORK
go work init
go work use tools/gopls mod
```
then opening the `$WORK` directory in your editor.
## When to manually configure `GOOS`, `GOARCH`, or `-tags`
As described in the first section, gopls v0.15.0 and later will try to
configure a new build scope automatically when you open a file that doesn't
match the system default operating system (`GOOS`) or architecture (`GOARCH`).
However, per the caveats listed in that section, this automatic behavior comes
with limitations. Customize your gopls environment by setting `GOOS` or
`GOARCH` in your
[`"build.env"`](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#env)
or `-tags=...` in your"
["build.buildFlags"](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#buildflags)
when:
- You want to modify the default build environment.
- Gopls is not guessing the `GOOS/GOARCH` combination you want to use for
cross platform development.
- You need to work on a file that is constrained by a user-defined build tags,
such as the build directive `//go:build mytag`.
## GOPATH mode
When opening a directory within a `GOPATH` directory, the workspace scope will
be just that directory and all directories contained within it. Note that
opening a large GOPATH directory can make gopls very slow to start.