|
1 | 1 | # Setting up your workspace
|
2 | 2 |
|
3 |
| -`gopls` supports both Go module and GOPATH modes. However, it needs a defined |
4 |
| -scope in which language features like references, rename, and implementation |
5 |
| -should operate. |
6 |
| - |
7 |
| -The following options are available for configuring this scope: |
8 |
| - |
9 |
| -## Module mode |
10 |
| - |
11 |
| -### One module |
12 |
| - |
13 |
| -If you are working with a single module, you can open the module root (the |
14 |
| -directory containing the `go.mod` file), a subdirectory within the module, |
15 |
| -or a parent directory containing the module. |
| 3 | +**In general, `gopls` should work when you open a Go file contained in your |
| 4 | +workspace folder**. If it isn't working for you, or if you want to better |
| 5 | +understand how gopls models your workspace, please read on. |
16 | 6 |
|
17 |
| -**Note**: If you open a parent directory containing a module, it must **only** |
18 |
| -contain that single module. Otherwise, you are working with multiple modules. |
| 7 | +## Workspace builds |
19 | 8 |
|
20 |
| -### Multiple modules |
21 |
| - |
22 |
| -Gopls has several alternatives for working on multiple modules simultaneously, |
23 |
| -described below. Starting with Go 1.18, Go workspaces are the preferred solution. |
24 |
| - |
25 |
| -#### Go workspaces (Go 1.18+) |
| 9 | +`gopls` supports both Go module and GOPATH modes. However, it needs a defined |
| 10 | +scope in which language features like references, rename, and implementation |
| 11 | +should operate. Put differently, gopls needs to infer which `go build` |
| 12 | +invocations you would use to build your workspace, including the working |
| 13 | +directory, environment, and build flags. |
| 14 | + |
| 15 | +Starting with `[email protected]`, gopls will try to guess the builds you are |
| 16 | +working on based on the set of open files. When you open a file in a workspace |
| 17 | +folder, gopls will check whether the file is contained in a module, `go.work` |
| 18 | +workspace, or GOPATH directory, and configure the build accordingly. |
| 19 | +Additionally, if you open a file that is constrained to a different operating |
| 20 | +system or architecture, for example opening `foo_windows.go` when working on |
| 21 | +Linux, gopls will create a scope with `GOOS` and `GOARCH` set to a value that |
| 22 | +matches the file. |
| 23 | + |
| 24 | +For example, suppose we had a repository with three modules: `moda`, `modb`, |
| 25 | +and `modc`, and a `go.work` file using modules `moda` and `modb`. If we open |
| 26 | +the files `moda/a.go`, `modb/b.go`, `moda/a_windows.go`, and `modc/c.go`, gopls |
| 27 | +will automatically create three builds: |
| 28 | + |
| 29 | + |
| 30 | + |
| 31 | +This allows `gopls` to _just work_ when you open a Go file, but it does come with |
| 32 | +several caveats: |
| 33 | + |
| 34 | +- This causes gopls to do more work, since it is now tracking three builds |
| 35 | + instead of one. However, the recent |
| 36 | + [scalability redesign](https://go.dev/blog/gopls-scalability) |
| 37 | + allows much of this work to be avoided through efficient caching. |
| 38 | +- In some cases this may cause gopls to do more work, since gopls is now |
| 39 | + tracking three builds instead of one. However, the recent |
| 40 | + [scalability redesign](https://go.dev/blog/gopls-scalability) allows us |
| 41 | + to avoid most of this work by efficient caching. |
| 42 | +- For operations originating from a given file, including finding references |
| 43 | + and implementations, gopls executes the operation in |
| 44 | + _the default build for that file_. For example, finding references to |
| 45 | + a symbol `S` from `foo_linux.go` will return references from the Linux build, |
| 46 | + and finding references to the same symbol `S` from `foo_windows.go` will |
| 47 | + return references from the Windows build. This is done for performance |
| 48 | + reasons, as in the common case one build is sufficient, but may lead to |
| 49 | + surprising results. Issues [#65757](https://go.dev/issue/65757) and |
| 50 | + [#65755](https://go.dev/issue/65755) propose improvements to this behavior. |
| 51 | +- When selecting a `GOOS/GOARCH` combination to match a build-constrained file, |
| 52 | + `gopls` will choose the first matching combination from |
| 53 | + [this list](https://cs.opensource.google/go/x/tools/+/master:gopls/internal/cache/port.go;l=30;drc=f872b3d6f05822d290bc7bdd29db090fd9d89f5c). |
| 54 | + In some cases, that may be surprising. |
| 55 | +- When working in a `GOOS/GOARCH` constrained file that does not match your |
| 56 | + default toolchain, `CGO_ENABLED=0` is implicitly set. This means that `gopls` |
| 57 | + will not work in files including `import "C"`. Issue |
| 58 | + [#65758](https://go.dev/issue/65758) may lead to improvements in this |
| 59 | + behavior. |
| 60 | +- `gopls` is not able to guess build flags that include arbitrary user-defined |
| 61 | + build constraints. For example, if you are trying to work on a file that is |
| 62 | + constrained by the build directive `//go:build special`, gopls will not guess |
| 63 | + that it needs to create a build with `"buildFlags": ["-tags=special"]`. Issue |
| 64 | + [#65089](https://go.dev/issue/65089) proposes a heuristic by which gopls |
| 65 | + could handle this automatically. |
| 66 | + |
| 67 | +We hope that you provide feedback on this behavior by upvoting or commenting |
| 68 | +the issues mentioned above, or opening a [new issue](https://go.dev/issue/new) |
| 69 | +for other improvements you'd like to see. |
| 70 | + |
| 71 | +## When to use a `go.work` file for development |
26 | 72 |
|
27 | 73 | Starting with Go 1.18, the `go` command has native support for multi-module
|
28 |
| -workspaces, via [`go.work`](https://go.dev/ref/mod#workspaces) files. These |
29 |
| -files are recognized by gopls starting with `[email protected]`. |
30 |
| - |
31 |
| -The easiest way to work on multiple modules in Go 1.18 and later is therefore |
32 |
| -to create a `go.work` file containing the modules you wish to work on, and set |
33 |
| -your workspace root to the directory containing the `go.work` file. |
34 |
| - |
35 |
| -For example, suppose this repo is checked out into the `$WORK/tools` directory. |
36 |
| -We can work on both `golang.org/x/tools` and `golang.org/x/tools/gopls` |
37 |
| -simultaneously by creating a `go.work` file using `go work init`, followed by |
38 |
| -`go work use MODULE_DIRECTORIES...` to add directories containing `go.mod` files to the |
39 |
| -workspace: |
| 74 | +workspaces, via [`go.work`](https://go.dev/ref/mod#workspaces) files. `gopls` |
| 75 | +will recognize these files if they are present in your workspace. |
| 76 | + |
| 77 | +Use a `go.work` file when: |
| 78 | + |
| 79 | +- You want to work on multiple modules simultaneously in a single logical |
| 80 | + build, for example if you want changes to one module to be reflected in |
| 81 | + another. |
| 82 | +- You want to improve `gopls'` memory usage or performance by reducing the number |
| 83 | + of builds it must track. |
| 84 | +- You want `gopls` to know which modules you are working on in a multi-module |
| 85 | + workspace, without opening any files. For example, if you want to use |
| 86 | + `workspace/symbol` queries before any files are open. |
| 87 | +- You are using `[email protected]` or earlier, and want to work on multiple |
| 88 | + modules. |
| 89 | + |
| 90 | +For example, suppose this repo is checked out into the `$WORK/tools` directory, |
| 91 | +and [`x/mod`](https://pkg.go.dev/golang.org/x/mod) is checked out into |
| 92 | +`$WORK/mod`, and you are working on a new `x/mod` API for editing `go.mod` |
| 93 | +files that you want to simultaneously integrate into `gopls`. |
| 94 | + |
| 95 | +You can work on both `golang.org/x/tools/gopls` and `golang.org/x/mod` |
| 96 | +simultaneously by creating a `go.work` file: |
40 | 97 |
|
41 | 98 | ```sh
|
42 | 99 | cd $WORK
|
43 | 100 | go work init
|
44 |
| -go work use ./tools/ ./tools/gopls/ |
| 101 | +go work use tools/gopls mod |
45 | 102 | ```
|
46 | 103 |
|
47 |
| -...followed by opening the `$WORK` directory in our editor. |
48 |
| - |
49 |
| -#### DEPRECATED: Experimental workspace module (Go 1.17 and earlier) |
50 |
| - |
51 |
| -**This feature is deprecated and will be removed in future versions of gopls. |
52 |
| -Please see [issue #52897](https://go.dev/issue/52897) for additional |
53 |
| -information.** |
54 |
| - |
55 |
| -With earlier versions of Go, `gopls` can simulate multi-module workspaces by |
56 |
| -creating a synthetic module requiring the modules in the workspace root. |
57 |
| -See [the design document](https://github.com/golang/proposal/blob/master/design/37720-gopls-workspaces.md) |
58 |
| -for more information. |
59 |
| - |
60 |
| -This feature is experimental, and will eventually be removed once `go.work` |
61 |
| -files are accepted by all supported Go versions. |
62 |
| - |
63 |
| -You can enable this feature by configuring the |
64 |
| -[experimentalWorkspaceModule](settings.md#experimentalworkspacemodule-bool) |
65 |
| -setting. |
66 |
| - |
67 |
| -#### Multiple workspace folders |
68 |
| - |
69 |
| -If neither of the above solutions work, and your editor allows configuring the |
70 |
| -set of |
71 |
| -["workspace folders"](https://microsoft.github.io/language-server-protocol/specifications/specification-3-17/#workspaceFolder) |
72 |
| -used during your LSP session, you can still work on multiple modules by adding |
73 |
| -a workspace folder at each module root (the locations of `go.mod` files). This |
74 |
| -means that each module has its own scope, and features will not work across |
75 |
| -modules. |
76 |
| - |
77 |
| -In VS Code, you can create a workspace folder by setting up a |
78 |
| -[multi-root workspace](https://code.visualstudio.com/docs/editor/multi-root-workspaces). |
79 |
| -View the [documentation for your editor plugin](../README.md#editor) to learn how to |
80 |
| -configure a workspace folder in your editor. |
81 |
| - |
82 |
| -### GOPATH mode |
| 104 | +...followed by opening the `$WORK` directory in your editor. |
83 | 105 |
|
84 |
| -When opening a directory within your GOPATH, the workspace scope will be just |
85 |
| -that directory. |
| 106 | +## When to manually configure `GOOS`, `GOARCH`, or `-tags` |
86 | 107 |
|
87 |
| -### At your own risk |
| 108 | +As described in the first section, `[email protected]` and later will try to |
| 109 | +configure a new build scope automatically when you open a file that doesn't |
| 110 | +match the system default operating system (`GOOS`) or architecture (`GOARCH`). |
88 | 111 |
|
89 |
| -Some users or companies may have projects that encompass one `$GOPATH`. If you |
90 |
| -open your entire `$GOPATH` or `$GOPATH/src` folder, the workspace scope will be |
91 |
| -your entire `GOPATH`. If your GOPATH is large, `gopls` to be very slow to start |
92 |
| -because it will try to find all of the Go files in the directory you have |
93 |
| -opened. It will then load all of the files it has found. |
| 112 | +However, per the caveats listed in that section, this automatic behavior comes |
| 113 | +with limitations. Customize your `gopls` environment by setting `GOOS` or |
| 114 | +`GOARCH` in your |
| 115 | +[`"build.env"`](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#env-mapstringstring) |
| 116 | +or `-tags=...` in your" |
| 117 | +["build.buildFlags"](https://github.com/golang/tools/blob/master/gopls/doc/settings.md#buildflags-string) |
| 118 | +when: |
94 | 119 |
|
95 |
| -To work around this case, you can create a new `$GOPATH` that contains only the |
96 |
| -packages you want to work on. |
| 120 | +- You want to modify the default build environment. |
| 121 | +- `gopls` is not guessing the `GOOS/GOARCH` combination you want to use for |
| 122 | + cross platform development. |
| 123 | +- You need to work on a file that is constrained by a user-defined build tags, |
| 124 | + such as the build directive `//go:build special`. |
97 | 125 |
|
98 |
| ---- |
| 126 | +## GOPATH mode |
99 | 127 |
|
100 |
| -If you have additional use cases that are not mentioned above, please |
101 |
| -[file a new issue](https://github.com/golang/go/issues/new). |
| 128 | +When opening a directory within your `GOPATH`, the workspace scope will be just |
| 129 | +that directory and all directories contained within it. Note that opening |
| 130 | +a large GOPATH directory can make gopls very slow to start. |
0 commit comments