# 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 [![PkgGoDev](https://pkg.go.dev/badge/golang.org/x/tools/gopls/internal)](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. ![Gopls architecture](architecture.svg) 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. ![A diagnostic due to a type error](../assets/diagnostic-typeerror.png) 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. ![A diagnostic due to an analysis finding](../assets/diagnostic-analysis.png) 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. ![An analyzer diagnostic with two alternative fixes](../assets/remove-unusedparam-before.png) 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. ![Before extracting a function](../assets/extract-function-before.png) ![After extracting a function](../assets/extract-function-after.png) - **`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: ![Before extracting a var](../assets/extract-var-before.png) ![After extracting a var](../assets/extract-var-after.png) - **`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. ![Before extracting all occurrences of EXPR](../assets/extract-var-all-before.png) ![After extracting all occurrences of EXPR](../assets/extract-var-all-after.png) - **`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`. ![Before: select the declarations to move](../assets/extract-to-new-file-before.png) ![After: the new file is based on the first symbol name](../assets/extract-to-new-file-after.png) ## `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: ![Before: select Refactor... Inline call to sum](../assets/inline-before.png) ![After: the call has been replaced by the sum logic](../assets/inline-after.png) 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. ![The parameter x is unused](../assets/remove-unusedparam-before.png) ![The parameter x has been deleted](../assets/remove-unusedparam-after.png) 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: ![Convert to interpreted](../assets/convert-string-interpreted.png) ![Convert to raw](../assets/convert-string-raw.png) 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. ![Before "Invert if condition"](../assets/invert-if-before.png) ![After "Invert if condition"](../assets/invert-if-after.png) ### `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`): ![Before "Fill slog.HandlerOptions"](../assets/fill-struct-before.png) ![After "Fill slog.HandlerOptions"](../assets/fill-struct-after.png) 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. ![Before "Add cases for Addr"](../assets/fill-switch-before.png) ![After "Add cases for Addr"](../assets/fill-switch-after.png) 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: ![Before "Add cases for Addr"](../assets/fill-switch-enum-before.png) ![After "Add cases for Addr"](../assets/fill-switch-enum-after.png) ### `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: ![Zero Config gopls](assets/zeroconfig.png) 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.