# Vscode Go
> * [Overview of Extension Features](features.md)
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/Home.md
Welcome to the VSCode Go Wiki!
### User Documentation
* [Overview of Extension Features](features.md)
* [Debugging Feature](debugging)
* [Diagnostics](https://github.com/golang/tools/blob/master/gopls/doc/analyzers.md)
* [Setting Up Your Workspace](https://github.com/golang/tools/blob/master/gopls/doc/workspace.md)
* [Available Settings](settings.md)
* [List of Extension Commands](commands.md)
* [Commonly Used `tasks.json` Setup](tasks.md)
* [3rd-party Tools Used By Extension](tools.md)
* [User Interface](ui.md)
* [FAQs](faq.md)
* [Troubleshooting](troubleshooting.md)
* [Advanced Topics](advanced.md)
* [How to Contribute](contributing.md)
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/advanced.md
# Advanced topics
This document describes more advanced ways of working with the VS Code Go
extension.
## Formatting Code and Organizing Imports
When you have multiple formatter extensions, be sure to set this
extension as the default formatter for go language.
```json5
"[go]": {
"editor.defaultFormatter": "golang.go"
}
```
Formatting and organizing imports are enabled by default. You
can choose to disable them by configuring the following settings.
```json5
"[go]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.organizeImports": false
}
}
```
## Choosing a different version of Go
The extension chooses the `go` command using the `PATH` (or `Path`) environment
variable by default. You can configure the extension to choose a different
version of `go` with one of the following options.
* (Preferred) Adjust your `PATH` or `Path` environment variable, and *open VS
Code with the adjusted environment* variable, or
* Use the Go extension's `"Go: Choose Go Environment"` command that opens a
[menu](ui.md) to change the `go` version, or
* Use the `"go.alternateTools"` settings and specify the absolute path to the
`go` command. `"go.alternateTools": { "go": "/path/to/go/command" }`
**note**: For historical reasons, some users configure the `"go.goroot"`
settings or the `GOROOT` environment variable to select the Go SDK location.
With recent versions of Go, that's unnecessary in most cases.
## Configuring the installation of command-line tools
The `Go: Install/Update Tools` command uses the `go get` command to download and
install requested tools. By default, `go get` will install the compiled tools in
one of the following directories.
* the directory the `GOBIN` environment variable specifies, or
* the `bin` directory under the first `GOPATH` (or `"go.gopath"`) directory, or
* the `$HOME/go/bin` (or `$USERPROFILE/go/bin`) directory.
Some users prefer to choose a different installation location. In that case, use
the `"go.toolsGopath"` setting.
The extension finds the required tools by their names (`go`, `gopls`, `dlv`,
etc.). The `"go.alternateTools"` setting provides a way to configure the
extension to use different tool location, for example a wrapper with a different
name.
The extension uses pinned versions of command-line tools. See the pinned versions
in tools information
[here](https://github.com/golang/vscode-go/blob/master/extension/src/goToolsInformation.ts).
To use an alternate version of a tool install it manually with with go install.
## Using a custom linter
A commonly customized feature is the linter, which is the tool used to provide
coding style feedback and suggestions. This extension supports linters such as
`staticcheck`, `golangci-lint`, and `revive`. You can choose one of them using
the `"go.lintTool"` setting. For customization of the linter, please consult the
linter's documentation.
Note that if you are using `staticcheck`, you can enable it to run within
`gopls` by setting `"gopls": { "ui.diagnostic.staticcheck": true }`.
## Working on the Go standard library and the Go tools
This extension can be used for developing the standard library with additional
configuration.
First, you **must open the `src/` folder in VS Code**, not the Go tree root.
Then, you need to configure the workspace, by placing the following in
`src/.vscode/settings.json`. [Command Palette] ->
`Preferences: Open Workspace Settings (JSON)` will open the settings file.
```json5
{
// Use the local go tool. This needs to be built with make.bash.
"go.alternateTools": {
"go": "~/godev/bin/go"
},
//
// Below is optional.
//
// Build a separate set of tools. For golang/vscode-go#294.
"go.toolsGopath": "~/.vscode/godev",
// Don't reformat HTML files since we have a custom style.
"html.format.enable": false
}
```
The above assumes the Go tree is checked out at `~/godev`. If your Go tree is
somewhere else, modify `go.alternateTools.go` to point to the go *binary*
accordingly. Many underlying tools including `gopls` invoke the go command
(`go list`, etc), so we assume the binary isn't completely broken.
You can add `.vscode` to `.git/info/exclude` to avoid risking checking
`settings.json` into git.
If you see an "inconsistent vendoring" error, please report it at
[golang/go#40250](https://github.com/golang/go/issues/40250).
[Command Palette]: https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/commands.md
# Commands
In addition to integrated editing features, this extension offers a number of commands, which can be executed manually through the [Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette) (Ctrl+Shift+P on Linux/Windows or Cmd+Shift+P on Mac OS).
Some of these commands are also available in the VS Code context menu (right-click). To control which of these commands show up in the editor context menu, update the [`"go.editorContextMenuCommands"`](settings.md#go.editorContextMenuCommands) setting.
All commands provided by this extension have the prefix `Go:`.
## Latest changes
The commands described below are up-to-date as of June 2020. We do our best to keep documentation current, but if a command is missing, you can always consult the full list in the Extensions view.
To view this list:
1. Navigate to the Extensions view (Ctrl+Shift+X).
2. Find the Go extension and click on it to open the Extension Editor.
3. Click on the `Feature Contributions` tab.
4. Scroll through the list under `Commands`.
Finally, you can also see a full list by using a meta command: `Go: Show All Commands...`.
## Detailed list
### `Go: Current GOPATH`
See the currently set GOPATH.
### `Go: Current GOROOT`
See the currently set GOROOT.
### `Go: Locate Configured Go Tools`
List all the Go tools being used by this extension along with their locations.
### `Go: Test Function At Cursor`
Runs a unit test at the cursor.
### `Go: Test Function At Cursor or Test Previous`
Runs a unit test at the cursor if one is found, otherwise re-runs the last executed test.
### `Go: Subtest At Cursor`
Runs a sub test at the cursor.
### `Go: Debug Subtest At Cursor`
Debug a sub test at the cursor.
### `Go: Benchmark Function At Cursor`
Runs a benchmark at the cursor.
### `Go: Debug Test At Cursor`
Debug test at the cursor.
### `Go: Test File`
Runs all unit tests in the current file.
### `Go: Test Package`
Runs all unit tests in the package of the current file.
### `Go: Toggle Hide System Goroutines`
Toggles hiding the system goroutines from the active debug session call stack view.
### `Go Test: Refresh`
Refresh a test in the test explorer. Only available as a context menu option in the test explorer.
### `Go Test: Show Last Profile`
Show last captured profile
### `Go Test: Profile`
Run a test and capture a profile
### `Go Test: Delete Profile`
Delete selected profile
### `Go: Show pprof file`
Internal use. Open a pprof profile file.
### `Go: Benchmark Package`
Runs all benchmarks in the package of the current file.
### `Go: Benchmark File`
Runs all benchmarks in the current file.
### `Go: Test All Packages In Workspace`
Runs all unit tests from all packages in the current workspace.
### `Go: Test Previous`
Re-runs the last executed test.
### `Go: Debug Previous`
Re-runs the last debugged test run through a codelens or "Go: Debug Test at Cursor" command.
### `Go: Toggle Test Coverage In Current Package`
Displays test coverage in the current package.
### `Go: Generate Unit Tests For Package`
Generates unit tests for the current package using gotests
### `Go: Generate Unit Tests For File`
Generates unit tests for the current file using gotests
### `Go: Generate Unit Tests For Function`
Generates unit tests for the selected function in the current file using gopls
### `Go: Generate Unit Tests For Function (legacy)`
Generates unit tests for the selected function in the current file using gotests
### `Go: Generate Interface Stubs`
Generates method stub for implementing the provided interface and inserts at the cursor.
### `Go: Extract Language Server Logs To Editor`
Extract logs in the `gopls (server)` output channel to the editor.
### `Go: Welcome`
Open the welcome page for the Go extension.
### `Go: Toggle compiler optimization details`
Toggle the per-package flag that causes compiler optimization details to be reported as diagnostics
### `Go: Add Import`
Add an import declaration
### `Go: Add Package to Workspace`
Add a package from the imports list to the workspace.
### `Go: Install/Update Tools`
install/update the required go packages
### `Go: Toggle Test File`
Toggles between file in current active editor and the corresponding test file.
### `Go: Toggle Vulncheck`
Toggle the display of vulnerability analysis in dependencies.
### `Go: Start language server's maintainer interface`
Start the Go language server's maintainer interface (a web server).
### `Go: Add Tags To Struct Fields`
Add tags configured in go.addTags setting to selected struct using gomodifytags (via gopls)
### `Go: Remove Tags From Struct Fields`
Remove tags configured in go.removeTags setting from selected struct using gomodifytags (via gopls)
### `Go: Show All Commands...`
Shows all commands from the Go extension in the quick pick
### `Go: Browse Packages`
Browse packages and Go files inside the packages.
### `Go: Get Package`
Run `go get -v` on the package on the current line.
### `Go: Run on Go Playground`
Upload the current selection or file to the Go Playground
### `Go: Lint Current Package`
Run linter in the package of the current file.
### `Go: Lint Workspace`
Run linter in the current workspace.
### `Go: Vet Current Package`
Run go vet in the package of the current file.
### `Go: Vet Workspace`
Run go vet in the current workspace.
### `Go: Build Current Package`
Build the package of the current file.
### `Go: Build Workspace`
Build the current workspace.
### `Go: Install Current Package`
Install the current package.
### `Go: Initialize go.mod`
Run `go mod init` in the workspace folder.
### `Go: Cancel Running Tests`
Cancels running tests.
### `Go: Apply Cover Profile`
Applies existing cover profile.
### `Go: Restart Language Server`
Restart the running instance of the language server
### `Go: Choose Go Environment`
Choose a different Go version or binary for this project. (WIP)
### `Go: Show Survey Configuration`
Show the current Go survey configuration
### `Go: Reset Survey Configuration`
Reset the current Go survey configuration history
### `Go: Reset Workspace State`
Reset keys in workspace state to undefined.
### `Go: Reset Global State`
Reset keys in global state to undefined.
### `Go Explorer: Refresh`
Refresh the Go explorer. Only available as a menu item in the explorer.
### `Go Explorer: Open File`
Open a file from the Go explorer. Only available as a menu item in the explorer.
### `Go: Edit Workspace Env`
Edit the Go Env for the active workspace.
### `Go: Reset Workspace Env`
Reset the Go Env for the active workspace.
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/compatibility.md
## Version Compatibility
The table below lists the *last* version of the extension
known to be compatible with old versions of Go, and the last versionof tools
compatible with it.
| Go version | Extension version | VS Code | Gopls | Delve |
| ---------- | ----------------- | ------- | --------- | ------------ |
| go1.20 | v0.42.1 | 1.75+ | v0.15.3 | v1.22.1 |
| go1.19 | v0.42.1 | 1.75+ | v0.15.3 | v1.21.2 |
| go1.18 | v0.41.3 | 1.75+ | v0.14.2 | v1.20.0 |
| go1.17 | v0.39.1 | 1.67+ | v0.11.0 | v1.9.1 |
| go1.16 | v0.39.1 | 1.67+ | v0.11.0 | v1.8.3 |
### References
* Gopls's [supported go versions](https://github.com/golang/tools/tree/master/gopls#supported-go-versions).
* Delve's [supported go versions](https://github.com/go-delve/delve/blob/master/pkg/goversion/compat.go).
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/contributing.md
# Contributing
We welcome your contributions and thank you for working to improve the Go development experience in VS Code.
This guide will explain the process of setting up your development environment to work on the VS Code Go extension, as well as the process of sending out your change for review.
Our canonical Git repository is located at https://go.googlesource.com/vscode-go and https://github.com/golang/vscode-go is a mirror.
* [Before you start coding](#before-you-start-coding)
* [Ask for help](#ask-for-help)
* [Debug Adapter](#debug-adapter)
* [Developing](#developing)
* [Setup](#setup)
* [Run](#run)
* [Test](#test)
* [Sideload](#sideload)
* [Mail your change for review](#mail-your-change-for-review)
* [Presubmit test in CI](#presubmit-test-in-ci)
## Before you start coding
If you are interested in fixing a bug or contributing a feature, please [file an issue](https://github.com/golang/vscode-go/issues/new/choose) first. Wait for a project maintainer to respond before you spend time coding.
If you wish to work on an existing issue, please add a comment saying so, as someone may already be working on it. A project maintainer may respond with advice on how to get started. If you're not sure which issues are available, search for issues with the [help wanted label](https://github.com/golang/vscode-go/labels/HelpWanted).
### Ask for help
The VS Code Go maintainers are reachable via the issue tracker and the [#vscode-dev] channel in the [Gophers Slack]. Please reach out on Slack with questions, suggestions, or ideas. If you have trouble getting started on an issue, we'd be happy to give pointers and advice.
### Language Server (`gopls`)
Many of the language features like auto-completion, documentation, diagnostics are implemented
by the Go language server ([`gopls`](https://pkg.go.dev/golang.org/x/tools/gopls)).
This extension communicates with `gopls` using [vscode LSP client library](https://github.com/microsoft/vscode-languageserver-node) from [`language/goLanguageServer.ts`](https://github.com/golang/vscode-go/tree/master/src/language).
For extending the language features or fixing bugs, please follow `gopls`'s
[contribution guide](https://github.com/golang/tools/blob/master/gopls/doc/contributing.md).
### Debug Adapter (`dlv dap`)
Debugging features are implemented by Delve (`dlv`) and its native DAP implementation
([`dlv dap`](https://github.com/go-delve/delve/blob/master/Documentation/api/dap/README.md)).
* goDebugConfiguration.ts: where launch configuration massaging occurs.
* goDebugFactory.ts: where a thin adapter that communicates with the `dlv dap` process is defined.
* [github.com/go-delve/delve](https://github.com/go-delve/delve/tree/master/service/dap): where native DAP implementation in Delve exists.
For extending the features of Delve, please follow `Delve` project's [contribution guide](https://github.com/go-delve/delve/blob/master/CONTRIBUTING.md).
The debugging feature documentation has a dedicated section for tips for development (See ["Developing"](https://github.com/golang/vscode-go/blob/master/docs/debugging.md#developing) section).
## Developing
### Setup
1) Install [node](https://nodejs.org/en/). Note: make sure that you are using `npm v7` or higher. The file format for `package-lock.json` (changed significantly)[https://docs.npmjs.com/cli/v7/configuring-npm/package-lock-json#file-format] in `npm v7`.
2) Clone the repository, run `npm ci`, and open VS Code:
```bash
git clone https://go.googlesource.com/vscode-go
cd vscode-go/extension
npm ci
code .
```
#### Lint
You can run `npm run lint` on the command-line to check for lint errors in your program. You can also use the [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) plugin to see errors as you code.
### Run
To run the extension with your patch, open the Run view (`Ctrl+Shift+D` or `⌘+⇧+D`), select `Launch Extension`, and click the Play button (`F5`).
This will open a new VS Code window with the title `[Extension Development Host]`. You can then open a folder that contains Go code and try out your changes.
You can also set breakpoints to debug your change.
If you make subsequent edits in the codebase, you can reload (`Ctrl+R` or `⌘+R`) the `[Extension Development Host]` instance of VS Code, which will load the new code. The debugger will automatically reattach.
## Test
1. `export GOPATH=/path/to/gopath/for/test`
2. `cd extension` -- most extension development work is done in the `extension` directory.
2. `go run tools/installtools/main.go` -- this will install all tools in the `GOPATH/bin` built from master/main.
3. There are currently two different types of tests in this repo:
- `npm run unit-test`: this runs unit tests defined in `test/unit`. They are light-weight tests that don't require `vscode` APIs.
- `npm run test`: this runs the integration tests defined in `test/integration` and `test/gopls`. They test logic that involve `vscode` APIs - which requires actually downloading & running Visual Studio Code (`code`) and loading the compiled extension/test code in it.
4. Before sending a CL, make sure to run
- `npm run lint`: this runs linter.
- `go run tools/generate.go -w=false -gopls=true`: this checks generated documentations are up-to-date.
### Testing Tips
#### (1) Running only a subset of integration or unit tests:
When running them from terminal:
- Option 1: Utilize `MOCHA_GREP` environment variable. That is equivalent with [`mocha --grep` flag](https://mochajs.org/#command-line-usage) that runs tests matching the given string or regexp. E.g. `MOCHA_GREP=gopls npm run test` which runs all integration tests whose suite/test names contain `"gopls"`.
- Option 2: modify the test source code and set the [`only`](https://mochajs.org/#exclusive-tests) or [`skip`](https://mochajs.org/#inclusive-tests) depending on your need. If necessary, you can also modify `test/integration/index.ts` or `test/gopls/index.ts` to include only the test files you want to focus on. Make sure to revert them before sending the changes for review.
#### (2) Debugging tests from VS Code:
`.vscode/launch.json` defines test launch configurations. To run the tests locally, open the Run view (`Ctrl+Shift+D`), select the relevant launch configuration, and hit the Play button (`F5`). Output and results of the tests, including any logging written with `console.log` will appear in the `DEBUG CONSOLE` tab.
You can supply environment variables (e.g. `MOCHA_GREP`) by modifying the launch configuration entry's `env` property.
- `Launch Unit Tests`: runs unit tests in `test/unit` (same as `npm run unit-test`)
- `Launch Extension Tests`: runs tests in `test/integration` directory (similar to `npm run test` but runs only tests under `test/integration` directory)
- `Launch Extension Tests with Gopls`: runs tests in `test/gopls` directory (similar to `npm run test` but runs only tests under `test/gopls` directory)
When you want to filter tests while debugging, utilize the `MOCAH_GREP` environment variable discussed previously - i.e., set the environment variable in the `env` property of the launch configuration.
#### (3) Using different versions of tools.
The tests will pick tools found from `GOPATH/bin` first. So, install the versions you want there.
## Running/Debugging the Extension
Select the [`Launch Extension`](https://github.com/golang/vscode-go/blob/e2a7fb523acffea3427ad7e369c3b2abc30b775b/.vscode/launch.json#L13) configuration, and hit the Play button (`F5`). This will build the extension and start a new VS Code window with the title `"[Extension Development Host]"` that uses the newly built extension. This instance has the node.js debugger attached automatically. You can debug using the VS Code Debug UI of the main window (e.g. set breakpoints, inspect variables, step, etc)
The VS Code window may have the folder or file used during your previous testing. If you want to change the folder during testing, close the folder by using "File > Close Folder", and open a new folder from the VS Code window under test.
### Debugging interaction with `gopls`
When developing features in `gopls`, you may need to attach a debugger to `gopls` and configure the extension to connect to the `gopls` instance using [the gopls deamon mode](https://github.com/golang/tools/blob/master/gopls/doc/daemon.md).
1. Start a gopls in deamon mode:
```
gopls -listen=:37374 -logfile=auto -debug=:0 serve
```
Or, if you use vscode for gopls development, you can configure `launch.json` of the `x/tools/gopls` project:
```
...
{
"name": "Launch Gopls",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/gopls",
"args": ["-listen=:37374", "-logfile=auto", "-debug=:0"],
"cwd": "<... directory where you want to run your gopls from ...",
}
...
```
2. Start the extension debug session using the `Launch Extension` configuration.
3. Configure the settings.json of the project open in the `"[Extension Development Host]"` window to start `gopls` that connects to the gopls we started in the step 1.
```
"go.languageServerFlags": ["-remote=:37374", "-rpc.trace"]
```
## Sideload
After making changes to the extension, you may want to test it end-to-end instead of running it in debug mode. To do this, you can sideload the extension.
1. `cd` into the `extension` directory.
3. Install all dependencies by running `npm ci`.
4. Run `npx vsce package`. This will generate a file with a `.vsix` extension in your current directory.
```bash
npm install -g vsce
cd vscode-go
npm ci
vsce package
```
5. Open a VS Code window, navigate to the Extensions view, and disable or uninstall the default Go extension.
6. Click on the "..." in the top-right corner, select "Install
from VSIX...", and choose the generated VSIX file. Alternatively, you can run `code --install-extension path/to/go.vsix` or open the Command Palette and run the `Extensions: Install from VSIX...` command.
## Mail your change for review
Once you have coded, built, and tested your change, it's ready for review! There are two ways to mail your change: (1) through [a GitHub pull request (PR)](https://golang.org/doc/contribute.html#sending_a_change_github), or (2) through a [Gerrit code review](https://golang.org/doc/contribute.html#sending_a_change_gerrit).
In either case, code review will happen in [Gerrit](https://www.gerritcodereview.com/), which is used for all repositories in the Go project. We strongly recommend the Gerrit code review if you plan to send many changes. GitHub pull requests will be mirrored into Gerrit, so you can follow a more traditional GitHub workflow, but you will still have to look at Gerrit to read comments.
The easiest way to start is by reading this [detailed guide for contributing to the Go project](https://golang.org/doc/contribute.html). Important things to note are:
* You will need to sign the [Google CLA](https://golang.org/doc/contribute.html#cla).
* Your commit message should follow the standards described on the [Commit Message Wiki](https://github.com/golang/go/wiki/CommitMessage).
* Your change should include tests (if possible).
Once you've sent out your change, a maintainer will take a look at your contribution within a few weeks. If you don't hear back, feel free to ping the issue or send a message to the [#vscode-dev] channel of the [Gophers Slack].
### Presubmit Test in CI
When you mail your CL or upload a new patch to an existing CL, *AND*
you or a fellow contributor assigns the `Commit-Queue=+1` label in Gerrit, all the
tests (including go test and typescript test) defined in vscode-go will be
triggered by `LUCI`.
`LUCI` will post the result as a comment, and add its `LUCI-TryBot-Result` vote
after all tests run completes.
To force a re-run of the LUCI CI, re-assigns the `Commit-Queue=+1` label in Gerrit.
[#vscode-dev]: https://gophers.slack.com/archives/CUWGEKH5Z
[Gophers Slack]: https://invite.slack.golangbridge.org/
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/debug-adapter.md
# Debug Adapter
The [Debug Adapter](../src/debugAdapter) runs in a separate Node.js process, which is spawned by VS Code when you debug Go code.
Please see the [Debug Adapter Protocol (DAP)](https://microsoft.github.io/debug-adapter-protocol/) to understand how the Debug Adapter acts as an intermediary between VS Code and the debugger ([Delve](https://github.com/go-delve/delve)).
This codebase is currently in flux: We are working on using [`Delve`'s native DAP implementation](https://github.com/go-delve/delve/tree/master/service/dap) instead of this one. Follow along with [golang/vscode-go#23](https://github.com/golang/vscode-go/issues/23) for updates on that work.
## Overview
* [Before you begin](#before-you-begin)
* [Debug only the Debug Adapter](#debug-only-the-debug-adapter)
* [Debug the VS Code extension and the Debug Adapter](#debug-the-entire-extension-including-the-debug-adapter)
* [Debug VS Code and the Debug Adapter](#debug-vs-code-and-the-debug-adapter)
## Before you begin
Before you start working on your change, please read the [contribution guidelines](contributing.md). This document assumes that you are already familiar with the process of [building](contributing.md#setup), [running](contributing.md#run), and [sideloading](contributing.md#sideload) the VS Code Go extension.
## Debug only the Debug Adapter
As a next step, you may want to debug the Debug Adapter, in order to understand how your change work with [Delve](tools.md#delve).
**NOTE: Since the Debug Adapter runs in a separate process from the rest of the extension, the steps below only enable you to debug the Debug Adapter code, not the entire extension. To debug the entire extension, as well as the debug adapter, see the instructions [below](#debug-the-entire-extension).**
1. Open the `vscode-go` folder in VS Code.
2. Go to the Run view and choose the `Launch as server` debug configuration.
3. Add breakpoints as needed to the [`vscode-go/src/debugAdapter/goDebug.ts`](../src/debugAdapter/goDebug.ts) file.
4. Open another instance of VS Code and open the Go project to debug.
5. Create a debug configuration for the Go project if it doesn't exist. Set `"debugServer": 4711` in the root of the configuration.
6. Start debugging your Go program using this configuration. This will trigger the breakpoints in [`goDebug.ts`](../src/debugAdapter/goDebug.ts) file.
## Debug the entire extension, including the Debug Adapter
You can take this step if your change modifies both the Debug Adapter and the main extension.
1. Open the `vscode-go` folder in VS Code.
2. Go to the Run view and choose the `Extension + Debug server` debug configuration. This combines `Launch Extension` and `Launch as server` debug configurations.
3. Add breakpoints as needed and start debugging (`F5`). It will start an Extension Development Host window and the Debug Adapter server process at port 4711. Debuggers are attached to both processes and the breakpoints will apply to both of them.
4. In the Extension Development Host window, open the Go application source code you'd like to debug. As above, create a debug configuration pointing to the program you want to debug. Add `"debugServer": 4711` to the root of the configuration. Then, run the debug configuration (`F5`), which will start debugging the Go application.
5. Combined debug information (call stacks, breakpoints, etc.) of the debugged Extension Development Host and the Debug Adapter will be displayed in the debug view of the original VS Code window. You can use the drop-down menu in the Debug toolbar to switch between the two instances (`Launch Extension` and `Launch as server`).
## Debug VS Code and the Debug Adapter
In some very rare cases, you may find it helpful to debug VS Code itself. An example of such a case might be verifying workbench behavior and state before executing debug adapter API calls.
First, ensure that you can [build and run VS Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#build-and-run) from source successfully.
Next, follow these steps:
1. Open an instance of VS Code that you have built from source.
2. [Sideload](contributing.md#sideload) your local `vscode-go` extension to the local instance of VS Code. This can be done by copying the contents of the `vscode-go` directory into `$HOME/.vscode-oss-dev/extensions/ms-vscode.go` (the exact location may vary by OS).
3. Open the `vscode` folder in Visual Studio Code.
4. Launch the VS Code debug instance (OSS - Code) by choosing the `Launch VS Code` debug configuration from the drop-down in the Run view. Add breakpoints as needed.
5. In another instance of VS Code, open the `vscode-go` folder. Choose the `Launch as server` debug configuration in the Run view. Add breakpoints as desired in the [`vscode-go/src/debugAdapter/goDebug.ts`](../src/debugAdapter/goDebug.ts) file.
6. Open the Go application you want to debug in the OSS Code instance initiated in step 4.
7. Create a debug configuration with the setting `"debugServer": 4711`.
8. Start debugging your Go application. Observe that any breakpoints you set in the VS Code and debug adapter codebases will be triggered.
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md
# Debugging with Legacy Debug Adapter
The Go extension historically used a small adapter program to work with the Go debugger, [Delve].
The extension transitioned to communicate with [Delve] directly but there are still cases you may
need to use the legacy debug adapter (e.g. remote debugging). This document explains how to use the
***legacy*** debug adapter.
* [Set up](#set-up)
* [Installation](#installation)
* [Configuration](#configuration)
* [Launch Configurations](#launch-configurations)
* [Specifying build tags](#specifying-build-tags)
* [Specifying other build flags](#specifying-other-build-flags)
* [Using VS Code Variables](#using-vs-code-variables)
* [Snippets](#snippets)
* [Debugging on Windows Subsystem for Linux (WSL)](#debugging-on-windows-subsystem-for-linux-wsl)
* [Remote Debugging](#remote-debugging)
* [Troubleshooting](#troubleshooting)
* [Read documentation and common issues](#read-documentation-and-common-issues)
* [Update Delve](#update-delve)
* [Check for multiple versions of Delve](#check-for-multiple-versions-of-delve)
* [Check your launch configuration](#check-your-launch-configuration)
* [Check your GOPATH](#check-your-gopath)
* [Enable logging](#enable-logging)
* [Optional: Debug the debugger](#optional-debug-the-debugger)
* [Ask for help](#ask-for-help)
* [Common issues](#common-issues)
## Set up
[Delve] (`dlv`) should be installed by default when you install this extension.
You may need to update `dlv` to the latest version to support the latest version
of Go. To install or update `dlv`, open the [Command Palette][]
(Windows/Linux: Ctrl+Shift+P; OSX: Shift+Command+P), select [`Go: Install/Update Tools`](settings.md#go-installupdate-tools), and select [`dlv`](tools.md#dlv).
## Selecting `legacy` debug adapter
To opt in to use the legacy debug adapter (`legacy`) by default, add the following in your VSCode settings.json.
```
"go.delveConfig": {
"debugAdapter": "legacy",
}
```
If you want to use the legacy mode for only a subset of your launch configurations, you can use [the `debugAdapter` attribute](#launchjson-attributes) to switch between `"dlv-dap"` and `"legacy"` mode.
For [Remote Debugging](#remote-debugging) (launch configuration with `"mode": "remote"` attribute),
the extension will use the `"legacy"` mode by default, so setting this attribute won't be necessary.
Throughout this document, we assume that you opted in to use the legacy debug adapter.
For debugging using the new debug adapter (default, `"dlv-dap"` mode), please see the documentation about [Debugging](https://github.com/golang/vscode-go/tree/master/docs/debugging-legacy.md).
### Configuration
You may not need to configure any settings to start debugging your programs, but you should be aware that the debugger looks at the following settings.
* Related to [`GOPATH`](gopath.md):
* [`go.gopath`](settings.md#go.gopath)
* [`go.inferGopath`](settings.md#go.inferGopath)
* [`go.delveConfig`](settings.md#go.delveConfig)
* `apiVersion`: Controls the version of the Delve API used (default: `2`).
* `dlvLoadConfig`: The configuration passed to Delve, which controls how variables are shown in the Debug pane. Not applicable when `apiVersion` is 1.
* `maxStringLen`: Maximum number of bytes read from a string (default: `64`).
* `maxArrayValues`: Maximum number of elements read from an array, slice, or map (default: `64`).
* `maxStructFields`: Maximum number of fields read from a struct. A setting of `-1` indicates that all fields should be read (default: `-1`).
* `maxVariableRecurse`: How far to recurse when evaluating nested types (default: `1`).
* `followPointers`: Automatically dereference pointers (default: `true`).
* `showGlobalVariables`: Show global variables in the Debug view (default: `false`).
* `debugAdapter`: Controls which debug adapter to use (default: `legacy`).
* `substitutePath`: Path mappings to apply to get from a path in the editor to a path in the compiled program (default: `[]`).
There are some common cases when you might want to tweak the Delve configurations.
* To change the default cap of 64 on string and array length when inspecting variables in the Debug view, set `maxStringLen`. (See a related known issue: [golang/vscode-go#126](https://github.com/golang/vscode-go/issues/126)).
* To evaluate nested variables in the Run view, set `maxVariableRecurse`.
## Launch Configurations
To get started debugging, run the command `Debug: Open launch.json`. If you did not already have a `launch.json` file for your project, this will create one for you. It will contain this default configuration, which can be used to debug the current package. With mode `auto`, the file that is currently open will determine whether to debug the program as a test. If `program` is instead set to a Go file, that file will determine which mode to run in.
```json5
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${fileDirname}",
"debugAdapter": "legacy",
"env": {},
"args": []
}
]
}
```
There are some more properties that you can adjust in the debug configuration:
Property | Description
-------- | -----------
name | The name for your configuration as it appears in the drop-down in the Run view.
type | Always leave this set to `"go"`. VS Code uses this setting to determine which extension should be used for debugging.
request | One of `launch` or `attach`. Use `attach` when you want to attach to a running process.
mode | For `launch` requests, one of `auto`, `debug`, `remote`, `test`, or `exec`. For `attach` requests, use `local` or `remote`.
program | In `test` or `debug` mode, this refers to the absolute path to the package or file to debug. In `exec` mode, this is the existing binary file to debug. Not applicable to `attach` requests.
env | Environment variables to use when debugging. Use the format: `{ "NAME": "VALUE" }`. Not applicable to `attach` requests.
envFile | Absolute path to a file containing environment variable definitions. The environment variables passed in via the `env` property override the ones in this file.
args | Array of command-line arguments to pass to the program being debugged.
showLog | If `true` and `logDest` is not set, Delve logs will be printed in the Debug Console panel. If `true` and `logDest` is set, logs will be written to the `logDest` file. This corresponds to `dlv`'s `--log` flag.
logOutput | Comma-separated list of Delve components (`debugger`, `gdbwire`, `lldbout`, `debuglineerr`, `rpc`) that should produce debug output when `showLog` is `true`. This corresponds to `dlv`'s `--log-output` flag.
logDest | Absolute path to the delve log output file. This corresponds to `dlv`'s `--log-dest` flag, but number (used for file descriptor) is disallowed. Supported only in dlv-dap mode on Linux and Mac.
buildFlags | Build flags to pass to the Go compiler. This corresponds to `dlv`'s `--build-flags` flag.
dlvFlags | Extra flags passed to `dlv`. See `dlv help` for the full list of supported flags. This is useful when users need to pass less commonly used or new flags such as `--only-same-user`, `--check-go-version`. Note that some flags such as `--log-output`, `--log`, `--log-dest`, `--api-version` already have corresponding properties in the debug configuration, and flags such as `--listen` and `--headless` are used internally. If they are specified in `dlvFlags`, they may be ignored or cause an error.
remotePath | If remote debugging (`mode`: `remote`), this should be the absolute path to the package being debugged on the remote machine. See the section on [Remote Debugging](#remote-debugging) for further details. [golang/vscode-go#45](https://github.com/golang/vscode-go/issues/45) is also relevant. Becomes the first mapping in substitutePath.
substitutePath | An array of mappings from an absolute local path to an absolute remote path that is used by the debuggee. The debug adapter will replace the local path with the remote path in all of the calls. The mappings are applied in order, and the first matching mapping is used. This can be used to map files that have moved since the program was built, different remote paths, and symlinked files or directories. This is intended to be equivalent to the [substitute-path](https://github.com/go-delve/delve/tree/master/Documentation/cli#config) configuration, and will eventually configure substitute-path in Delve directly.
cwd | The working directory to be used in running the program. If remote debugging (`mode`: `remote`), this should be the absolute path to the working directory being debugged on the local machine. The extension defaults to the workspace folder, or the workspace folder of the open file in multi root workspaces. See the section on [Remote Debugging](#remote-debugging) for further details. [golang/vscode-go#45](https://github.com/golang/vscode-go/issues/45) is also relevant.
processId | This is the process ID of the executable you want to debug. Applicable only when using the `attach` request in `local` mode. By setting this to the command name of the process, `${command:pickProcess}`, or`${command:pickGoProcess}` a quick pick menu will show a list of processes to choose from.
### Specifying [build tags](https://golang.org/pkg/go/build/#hdr-Build_Constraints)
If your program contains [build tags](https://golang.org/pkg/go/build/#hdr-Build_Constraints), you can use the `buildFlags` property. For example, if you build your code with:
```bash
go build -tags=whatever
```
Then, set:
```json5
"buildFlags": "-tags=whatever"
```
in your launch configuration. This property supports multiple tags, which you can set by using single quotes. For example:
```json5
"buildFlags": "-tags='first,second,third'"
```
### Specifying other build flags
The flags specified in `buildFlags` and `env.GOFLAGS` are passed to the Go compiler when building your program for debugging. Delve adds `-gcflags=all="-N -l"` to the list of build flags to disable optimizations. User specified buildFlags conflict with this setting, so the extension removes them ([Issue #117](https://github.com/golang/vscode-go/issues/117)). If you wish to debug a program using custom `-gcflags`, build the program using `go build` and launch using `exec` mode:
```json
{
"name": "Launch executable",
"type": "go",
"request": "launch",
"mode": "exec",
"program": "/absolute/path/to/executable"
}
```
Note that it is not recommended to debug optimized executables as Delve may not have the information necessary to properly debug your program.
### Using [VS Code variables]
Any property in the launch configuration that requires a file path can be specified in terms of [VS Code variables]. Here are some useful ones to know:
* `${workspaceFolder}` refers to the root of the workspace opened in VS Code. If using a multi root workspace, you must specify the folder name `${workspaceFolder:folderName}`
* `${fileWorkspaceFolder}` refers to the the current opened file's workspace folder.
* `${file}` refers to the currently opened file.
* `${fileDirname}` refers to the directory containing the currently opened file. This is typically also the name of the Go package containing this file, and as such, can be used to debug the currently opened package.
### Snippets
In addition to [VS Code variables], you can make use of [snippets] when editing the launch configuration in `launch.json`.
When you type `go` in the `launch.json` file, you will see snippet suggestions for debugging the current file or package or a given test function.
Below are the available sample configurations:
#### Debug the current file (`Go: Launch file`)
Recall that `${file}` refers to the currently opened file (see [Using VS Code Variables](#using-vs-code-variables)). For debugging a package that consists with multiple files, use `${fileDirname}` instead.
```json5
{
"name": "Launch file",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${file}"
}
```
#### Debug a single test function (`Go: Launch test function`)
Recall that `${workspaceFolder}` refers to the current workspace (see [Using VS Code Variables](#using-vs-code-variables)). You will need to manually specify the function name instead of `"MyTestFunction"`.
```json5
{
"name": "Launch test function",
"type": "go",
"request": "launch",
"mode": "test",
"program": "${workspaceFolder}",
"args": [
"-test.run",
"MyTestFunction"
]
}
```
#### Debug all tests in the given package (`Go: Launch test package`)
A package is a collection of source files in the same directory that are compiled together.
Recall that `${fileDirname}` refers to the directory of the open file (see [Using VS Code Variables](#using-vs-code-variables)).
```json5
{
"name": "Launch test package",
"type": "go",
"request": "launch",
"mode": "test",
"program": "${workspaceFolder}"
}
```
#### Attach to a running local process via its process ID (`Go: Attach to local process`)
Substitute `processName` with the name of the local process.
```json5
{
"name": "Attach to local process",
"type": "go",
"request": "attach",
"mode": "local",
"processId": "processName"
}
```
#### Attach to a running server (`Go: Connect to Server`)
```json5
{
"name": "Connect to server",
"type": "go",
"request": "attach",
"mode": "remote",
"remotePath": "${workspaceFolder}",
"port": 2345,
"host": "127.0.0.1"
}
```
#### Debug an existing binary
There is no snippet suggestion for this configuration.
```json
{
"name": "Launch executable",
"type": "go",
"request": "launch",
"mode": "exec",
"program": "/absolute/path/to/executable"
}
```
If passing arguments to or calling subcommands and flags from a binary, the `args` property can be used.
```json
{
"name": "Launch executable",
"type": "go",
"request": "launch",
"mode": "exec",
"program": "/absolute/path/to/executable",
"args": ["subcommand", "arg", "--flag"],
}
```
## Debugging on [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/)
If you are using using WSL, you will need the WSL 2 Linux kernel. See [WSL 2 Installation](https://docs.microsoft.com/en-us/windows/wsl/wsl2-install) and note the Window 10 build version requirements.
## Remote Debugging
To debug on a remote machine, you must first run a headless Delve server on the target machine. The examples below assume that you are in the same folder as the package you want to debug. If not, please refer to the [`dlv debug` documentation](https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_debug.md).
To start the headless Delve server:
```bash
dlv debug --headless --listen=:2345 --log --api-version=2
```
Any arguments that you want to pass to the program you are debugging must also be passed to this Delve server. For example:
```bash
dlv debug --headless --listen=:2345 --log -- -myArg=123
```
Then, create a remote debug configuration in your `launch.json`.
```json5
{
"name": "Launch remote",
"type": "go",
"request": "attach",
"mode": "remote",
"remotePath": "/absolute/path/dir/on/remote/machine",
"port": 2345,
"host": "127.0.0.1",
"cwd": "/absolute/path/dir/on/local/machine",
}
```
In the example, the VS Code debugger will run on the same machine as the headless `dlv` server. Make sure to update the `port` and `host` settings to point to your remote machine.
`remotePath` should point to the absolute path of the program being debugged in the remote machine. `cwd` should point to the absolute path of the working directory of the program being debugged on your local machine. This should be the counterpart of the folder in `remotePath`. See [golang/vscode-go#45](https://github.com/golang/vscode-go/issues/45) for updates regarding `remotePath` and `cwd`. You can also use the equivalent `substitutePath` configuration.
```json5
{
"name": "Launch remote",
"type": "go",
"request": "attach",
"mode": "remote",
"substitutePath": [
{
"from": "/absolute/path/dir/on/local/machine",
"to": "/absolute/path/dir/on/remote/machine",
},
],
"port": 2345,
"host": "127.0.0.1",
"cwd": "/absolute/path/dir/on/local/machine",
}
```
If you do not set, `remotePath` or `substitutePath`, then the debug adapter will attempt to infer the path mappings. See [golang/vscode-go#45](https://github.com/golang/vscode-go/issues/45) for more information.
When you run the `Launch remote` target, VS Code will send debugging commands to the `dlv` server you started, instead of launching it's own `dlv` instance against your program.
For further examples, see [this launch configuration for a process running in a Docker host](https://github.com/lukehoban/webapp-go/tree/debugging).
## Troubleshooting
Debugging is one of the most complex features offered by this extension. The features are not complete, and a new implementation is currently being developed (see [golang/vscode-go#23](https://github.com/golang/vscode-go/issues/23)).
The suggestions below are intended to help you troubleshoot any problems you encounter. If you are unable to resolve the issue, please take a look at the [current known debugging issues](https://github.com/golang/vscode-go/issues?q=is%3Aissue+is%3Aopen+label%3Adebug) or [file a new issue](https://github.com/golang/vscode-go/issues/new/choose).
### Read documentation and [common issues](#common-issues)
Start by taking a quick glance at the [common issues](#common-issues) described below. You can also check the [Delve FAQ](https://github.com/go-delve/delve/blob/master/Documentation/faq.md) in case the problem is mentioned there.
### Update Delve
If the problem persists, it's time to start troubleshooting. A good first step is to make sure that you are working with the latest version of Delve. You can do this by running the [`Go: Install/Update Tools`](settings.md#go-installupdate-tools) command and selecting [`dlv`](tools.md#dlv).
### Check your [launch configuration](#launch-configurations)
Next, confirm that your [launch configuration](#launch-configurations) is correct.
One common error is `could not launch process: stat ***/debug.test: no such file or directory`. You may see this while running in the `test` mode. This happens when the `program` attribute points to a folder with no test files, so ensure that the `program` attribute points to a directory containing the test files you wish to debug.
Also, check the version of the Delve API used in your [launch configuration](#launch-configurations). This is handled by the `–api-version` flag, `2` is the default. If you are debugging on a remote machine, this is particularly important, as the versions on the local and remote machines much match. You can change the API version by editing the [`launch.json` file](#launch-configurations).
### Check for multiple versions of Delve
You might have multiple different versions of [`dlv`](tools.md#dlv) installed, and VS Code Go could be using a wrong or old version. Run the [`Go: Locate Configured Go Tools`](settings.md#go-locate-configured-go-tools) command and see where VS Code Go has found `dlv` on your machine. You can try running `which dlv` to see which version of `dlv` you are using on the [command-line](https://github.com/go-delve/delve/tree/master/Documentation/cli).
To fix the issue, simply delete the version of `dlv` used by the Go extension. Note that the extension first searches for binaries in your `$GOPATH/bin` and then looks on your `$PATH`.
If you see the error message `Failed to continue: "Error: spawn EACCES"`, the issue is probably multiple versions of `dlv`.
### Try building your binary **without** compiler optimizations
If you notice `Unverified breakpoints` or missing variables, ensure that your binary was built **without** compiler optimizations. Try building the binary with `-gcflags="all=-N -l"`.
### Check your `GOPATH`
Make sure that the debugger is using the right [`GOPATH`](gopath.md). This is probably the issue if you see `Cannot find package ".." in any of ...` errors. Read more about configuring your [GOPATH](gopath.md) or [file an issue report](https://github.com/golang/vscode-go/issues/new/choose).
**As a work-around**, add the correct `GOPATH` as an environment variable in the `env` property in the `launch.json` file.
### Enable logging
Next, check the logs produced by Delve. These will need to be manually enabled. Follow these steps:
* Set `"showLog": true` in your launch configuration. This will show Delve logs in the Debug Console pane (Ctrl+Shift+Y).
* Set `"trace": "log"` in your launch configuration. Again, you will see logs in the Debug Console pane (Ctrl+Shift+Y). These logs will also be saved to a file and the path to this file will be printed at the top of the Debug Console.
* Set `"logOutput": "rpc"` in your launch configuration. You will see logs of the RPC messages going between VS Code and Delve. Note that for this to work, you must also have set `"showLog": true`.
* The `logOutput` attribute corresponds to the `--log-output` flag used by Delve. It is a comma-separated list of components that should produce debug output.
See [common issues](#common-issues) below to decipher error messages you may find in your logs.
With `"trace": "log"`, you will see the actual call being made to `dlv`. To aid in your investigation, you can copy that and run it in your terminal.
### **Optional**: Debug the debugger
This is not a required step, but if you want to continue digging deeper, you can, in fact, debug the debugger. The code for the debugger can be found in the [debug adapter module](../src/debugAdapter). See our [contribution guide](contributing.md) to learn how to [run](contributing.md#run) and [sideload](contributing.md#sideload) the Go extension.
### Ask for help
At this point, it's time to look at the [common issues](#common-issues) below or the [existing debugging issues](https://github.com/golang/vscode-go/issues?q=is%3Aissue+is%3Aopen+label%3Adebug) on the [issue tracker](https://github.com/golang/vscode-go/issues). If that still doesn't solve your problem, [file a new issue](https://github.com/golang/vscode-go/issues/new/choose).
## Common Issues
### delve/launch hangs with no messages on WSL
Try running ```delve debug ./main``` in the WSL command line and see if you get a prompt.
**_Solution_**: Ensure you are running the WSL 2 Kernel, which (as of 4/15/2020) requires an early release of the Windows 10 OS. This is available to anyone via the Windows Insider program. See [Debugging on WSL](#debugging-on-windows-subsystem-for-linux-wsl).
### could not launch process: could not fork/exec
The solution this issue differs based on your OS.
#### OSX
This usually happens on OSX due to signing issues. See the discussions in [Microsoft/vscode-go#717](https://github.com/Microsoft/vscode-go/issues/717), [Microsoft/vscode-go#269](https://github.com/Microsoft/vscode-go/issues/269) and [go-delve/delve#357](https://github.com/go-delve/delve/issues/357).
**_Solution_**: You may have to uninstall dlv and install it manually as described in the [Delve instructions](https://github.com/go-delve/delve/blob/master/Documentation/installation/osx/install.md#manual-install).
#### Linux/Docker
Docker has security settings preventing `ptrace(2)` operations by default within the container.
**_Solution_**: To run your container insecurely, pass `--security-opt=seccomp:unconfined` to `docker run`. See [go-delve/delve#515](https://github.com/go-delve/delve/issues/515) for references.
#### could not launch process: exec: "lldb-server": executable file not found in $PATH
This error can show up for Mac users using Delve versions 0.12.2 and above. `xcode-select --install` has solved the problem for a number of users.
### Debugging symlink directories
Since the debugger and go compiler use the actual filenames, extra configuration is required to debug symlinked directories. Use the `substitutePath` property to tell the debugAdapter how to properly translate the paths. For example, if your project lives in `/path/to/actual/helloWorld`, but the project is open in vscode under the linked folder `/path/to/hello`, you can add the following to your config to set breakpoints in the files in `/path/to/hello`:
```json5
{
"name": "Launch remote",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "/path/to/hello",
"substitutePath": [
{
"from": "/path/to/hello",
"to": "/path/to/actual/helloWorld",
},
],
}
```
This extension does not provide general support for debugging projects containing symlinks. If `substitutePath` does not meet your needs, please consider commenting on this issue that contains updates to symlink support reference [golang/vscode-go#622](https://github.com/golang/vscode-go/issues/622).
[Delve]: https://github.com/go-delve/delve
[VS Code variables]: https://code.visualstudio.com/docs/editor/variables-reference
[snippets]: https://code.visualstudio.com/docs/editor/userdefinedsnippets
[Command Palette]: https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/debugging.md
# Debugging
The Go extension allows you to launch or attach to Go programs for debugging.
You can inspect variables and stacks, set breakpoints, and do other debugging
activities using
[VS Code’s Debugging UI](https://code.visualstudio.com/docs/editor/debugging).
These debugging features are possible by using
[Delve](https://github.com/go-delve/delve), the Go debugger.
Previously, the Go extension communicated with Delve through a custom debug
adaptor program (`legacy` mode). Since
[`Delve`'s native debug adapter implementation](https://github.com/go-delve/delve/tree/master/service/dap)
is available, the Go extension is transitioning to deprecate the legacy debug
adapter in favor of direct communication with Delve via
[DAP](https://microsoft.github.io/debug-adapter-protocol/overview).
📣 **We are happy to announce that the new _`dlv-dap`_ mode of Delve
integration is enabled for _local_ _debugging_ by default. For
[_remote_ _debugging_](#remote-debugging) it is the default in
[pre-release versions](https://github.com/golang/vscode-go/blob/master/README.md#pre-release-version) and is available with stable builds on demand with
`"debugAdapter": "dlv-dap"` attribute in `launch.json` or `settings.json`!**
Many features and settings described in this document may be available only with
the new `dlv-dap` mode. For troubleshooting and configuring the legacy debug
adapter, see
[the legacy debug adapter documentation](https://github.com/golang/vscode-go/tree/master/docs/debugging-legacy.md).
## Get started
Open a file to debug (either `package main` source file or the test file) in the
editor, and select the `Run and Debug` button from
[the Run view](https://code.visualstudio.com/docs/editor/debugging#_run-view).
Alternatively, you can start debugging using `Start Debugging (F5)` command from
[the Run menu](https://code.visualstudio.com/docs/editor/debugging#_run-menu) or
from
[the Command Palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette)
(Linux/Windows: Ctrl+Shift+P, Mac: ⇧+⌘+P).
If you already have launch configurations for the project
(`.vscode/launch.json`), the Run view will display the configuration list to
choose from.
When no configuration is configured yet (no `.vscode/launch.json` file), the
extension will choose a default configuration based on the file open in the
editor.
❗ When you start debugging for
the first time or if the `dlv` executable on your system is too old to support
DAP, the Go extension may ask to install or update Delve. Follow the
instructions to install it, and then start the debugging session again.
To learn more about debugging in Go, watch
[Go: Writing and debugging fast, reliable, and efficient software](https://www.youtube.com/watch?v=6r08zGi38Tk&list=PLj6YeMhvp2S40Q-TEPEKOeypLvTVd5uME&index=1).
Review the [Features](#features) section for an overview of
the Go Extension's debug UI and available features.
### Stay up to date
[Delve’s native DAP implementation](https://github.com/go-delve/delve/tree/master/service/dap)
is under active development. Take advantage of the most recent features and bug
fixes by installing the latest version of `dlv` using the
**`Go:Install/Update`** Tools command from the Command Palette (Linux/Windows:
`Ctrl`+`Shift`+`P`, Mac: `Command`+`Shift`+`P`). The command will show `dlv` in
the tool list.
Once `dlv` is installed on your system, the extension will prompt you for update
whenever installing a newer version is necessary. You can set the
`go.toolsManagement.autoUpdate` setting so the extension can update `dlv`
automatically for you.
If you need to install `dlv` manually outside of VS Code, follow the instruction
in [Manually installing `dlv`](debugging.md#manually-installing-dlv). An example
of a situation where manual installation might be needed is if you are building
a dev container with the necessary tools preinstalled, or installing `dlv` built
from the tree head.
### Switch to legacy debug adapter
Note: The extension still uses the legacy debug adapter for remote debugging.
If you need to use the legacy debug adapter for local debugging (`legacy` mode)
by default, add the following in your VSCode settings.
```json
"go.delveConfig": {
"debugAdapter": "legacy",
}
```
When `mode` is set to `remote` you must explicitly set `debugAdapter` to
`dlv-dap` to override the legacy adapter default.
If you want to switch to `legacy` for only a subset of your launch
configurations, you can use
[the `debugAdapter` attribute](#launchjson-attributes) to switch between
`"dlv-dap"` and `"legacy"` mode.
If you chose to switch to legacy because of bugs or limitations in the new debug
adapter, [open an issue](https://github.com/golang/vscode-go/issues/new)
to help us improve.
## Features
For general debugging features such as inspecting variables, setting
breakpoints, and other activities that aren't language-dependent, review
[VS Code debugging](https://code.visualstudio.com/docs/editor/debugging).
### Configure
When you need more than the default debugging setup, you can create a launch
configuration file for the project.
To create a configuration file:
1. In the
[the Run view](https://code.visualstudio.com/docs/editor/debugging#_run-view),
click "create a launch.json file"
1. Choose **Go: Launch Package** from the debug configuration drop-down menu. VS
Code will create a `launch.json` file in a .vscode folder in your workspace
(project root folder) or in your
[user settings](https://code.visualstudio.com/docs/editor/debugging#_global-launch-configuration)
or
[workspace settings](https://code.visualstudio.com/docs/editor/multi-root-workspaces#_workspace-launch-configurations).
If you already have a `launch.json` for your project, you can open it using the
Command Palette **Open launch.json** command.
To add a new configuration to an existing `launch.json` file:
1. Open your `launch.json` file using the Command Palette **Open launch.json**
command.
1. Click the **Add Configuration** button to invoke the snippet IntelliSense.
There are many configuration attributes (see
[the Launch.json attributes](#launchjson-attributes) section). IntelliSense in
VS Code’s `launch.json` editor will help you navigate available options and
documentation.
### Launch
To launch and debug your project, select **Run** > **Start Debugging (F5)**.
The launch feature uses a `launch` request type configuration in your
`launch.json` file. Its `program` attribute needs to be the absolute path to
either the Go file, or folder containing the main package or test file. In this
mode, the Go extension will start the debug session by building and launching
the program. The launched program will be terminated when the debug session
ends.
* Supported modes
* `debug`: build and debug a main package
* `test`: build and debug a test
* `exec`: debug a precompiled binary
* The binary must be built with `go build -gcflags=all="-N -l"` to disable
inlining and optimizations that can interfere with debugging.
* `auto`: automatically choose between `debug` and `test` depending on the
open file
⚠️ For ["Remote Debugging"](#remote-debugging), add the `port` attribute to the
launch configuration. VS Code will connect to the external user-specified
`dlv dap` server at `host:port` and launch the target there.
For remote debugging, the `program` attribute must point to the absolute path to
the package or binary to debug in the remote host’s file system even when
`substitutePath` is specified.
### Attach
You can use this configuration to attach to a running process or a running debug
session.
* Supported modes
* `local`: attaches to a local process.
* The binary must be built with `go build -gcflags=all="-N -l"` to disable
inlining and optimizations that can interfere with debugging.
* `remote`: attaches to an in-progress debug session run by an external
server.
You can debug an already running program using the `local` mode type
configuration. The Go extension will start `dlv dap` and configure it to attach
to the specified process. Users can select the process to debug with one of the
following options:
* Specifying the numeric process id (PID) with the `processId` attribute.
* Specifying the target program name in the `processId` attribute. If there are
multiple processes matching the specified program name, the extension will
show the list of matching processes at the start of the debug session.
* Specifying `0` in the `processId` attribute and selecting the process from the
drop-down menu at the start of the debug session.
NOTE: For remote debugging, add the `port` attribute to
the launch configuration. VS Code will connect to the external user-specified
`dlv dap` server at `host:port` and attach to the target there.See
["remote debugging"](#remote-debugging) for more details).
You can connect to an already running remote debug session using the `remote`
mode. Specify optional `host` and required `port` for the external
`dlv --headless` server that already took program or process id details as
command-line arguments. See ["Remote Debugging"](#remote-debugging) for more
details).
When you end an attach debug session, the debug UI allows you to choose to:
* [DEFAULT] Disconnect: disconnect the client and:
* `local`: leave the target process running (dlv terminates).
* `remote`: let dlv decide if it can continue running (`--accept-multiclient`
mode only); if so, the target will stay in halted or running state it was in
at disconnect.
* `dlv debug/test/exec`: terminate the target process if dlv terminates.
* `dlv attach`: leave the target process running even if dlv terminates.
* Stop: stop the attached server and the target process.
### Debug actions
Once a debug session starts, the Debug toolbar will appear on the top of the
editor.
The available commands are:
* Continue / Pause F5
* Step Over (aka `next` in Delve) F10
* Step Into (aka `step` in Delve) F11
* Step Out (aka `stepout` in Delve) Shift+F11 or ⇧F11
* Restart (currently this is "Stop + Start") Ctrl+Shift+F5 or ⇧⌘F5
* Stop (terminate the debugee. Available in Launch request) Shift+F5 or ⇧F5
* Disconnect (detach from the debugee. Available only in Attach request)
Shift+F5 or ⇧F5
* Terminate (terminate the debugee. Available only in Attach request)
Alt+Shift+F5 or ⌥⇧F5
### Breakpoints
See
[VS Code’s Debug Documentation on Breakpoints](https://code.visualstudio.com/docs/editor/debugging#_breakpoints)
to get familiar with VS Code’s UI. The Go debugger supports multiple ways to
configure breakpoints.
* **Breakpoints**: you can set breakpoints by clicking on the editor margin or
using F9 on the current line. If the breakpoints can’t be set by Delve, VS
Code will show the failure reason and grey out the dot.
* **Conditional breakpoints**: you can specify breakpoint conditions (similar to
Delve’s
[`condition` command](https://github.com/go-delve/delve/tree/master/Documentation/cli#condition)).
* Expression condition: takes a boolean expression.
* Hit count: supports comparison operators (`>`, `>=`, `<`, `<=`, `==`, `!=`)
with an integer value. `% n` form means we should stop at the breakpoint
when the hitcount is a multiple of `n`.
* **Function Breakpoints**: breakpoints can be set based on function names.
Press the + button in the BREAKPOINTS section header and enter the location in
the form of `[:]`. This sets the breakpoint in the `line`
inside the `function`. The full syntax for `function` is
`.(*).` as specified in
[Delve’s location spec](https://github.com/go-delve/delve/blob/master/Documentation/cli/locspec.md#location-specifiers).
Function breakpoints are shown with a red triangle in the BREAKPOINTS section.
* **Logpoints**: a
[logpoint](https://code.visualstudio.com/docs/editor/debugging#_logpoints) is
a variant of breakpoint that does not 'break', but instead logs a message to
DEBUG CONSOLE and continues execution. Expressions within `{}` are
interpolated. For the list of acceptable expressions and syntax, see
[Delve's documentation](https://github.com/go-delve/delve/blob/master/Documentation/cli/expr.md#expressions).
### Data inspection
You can inspect variables in the VARIABLES section of the Run view or by
hovering over their source in the editor. Variable values and expression
evaluation are relative to the selected stack frame in the CALL section.
By default, the VARIABLES section hides global variables, and shows only local
variables and function arguments. However, you can still inspect global
variables from the DEBUG CONSOLE panel. If you prefer to have the VARIABLES
section show global variables, set the `showGlobalVariables` attribute in the
`launch.json` configuration, or set it in the `go.delveConfig` setting.
When you select a variable and right click from the VARIABLES section, the
context menu will present shortcuts to features such as:
* `Set Value`: you can set/modify simple string, numeric, pointer values. Using
composite literals, or memory allocation is not supported.
* `Copy Value`: this copies the value in clipboard.
* `Copy as Expression`: this is useful when you need to query from the REPL in
the DEBUG CONSOLE panel.
* `Add to Watch`: this will automatically add the expression to the WATCH
section.
Shadowed variables will be marked with `()`.
⚠️ Delve debugger imposes variable loading limits to prevent loading too many
variables at once and negatively impacting debugging latency. The `dlv-dap` mode
uses a different approach. It takes advantage of the interactive UI features to
provide on-demand loading of individual variables, paging of arrays, slices and
maps and increased string limits depending on the context. We continue to
explore additional interactive features to balance performance and usability of
variable loading and look forward to your feedback.
You can inspect variables and evaluate expressions from the DEBUG CONSOLE panel
too. Acceptable expressions are either
* A valid
[Delve expression](https://github.com/go-delve/delve/blob/master/Documentation/cli/expr.md),
or
* `call ` to call functions.
Variables and expressions accepted in DEBUG CONSOLE can be also registered in
the Run view’s WATCH section, so they can be evaluated automatically as you
debug. The "Add to Watch" feature from the VARIABLES section is convenient when
you want to register interesting variables.
⚠️ Function call feature is highly EXPERIMENTAL due to the limitation in Go
runtime. Registering function calls in the WATCH section can often be
problematic. Pause, stop, and disconnect will not work while a function call is
running.
Hover over variables in editors during debugging shows the value of the
variable. For this feature, VS Code extracts the variable expression and makes a
request to the debugger to evaluate the expression. Delve evaluates the
expression relative to the highlighted stack frame chosen in the CALL STACK. By
default, that is the current top-most frame.
⚠️ Limitation
* VS Code heuristically determines the variable expression without full
understanding of the scope & the currently selected frame. Delve tries to
evaluate the provided expression in the selected frame. As a result, hover
over variables outside the selected frame’s function may present incorrect
information.
### Call stack
You can inspect all goroutines and their stacks in the CALL STACK section. The
CALL STACK section UI allows switching between goroutines or selecting a
different stack frame. As a different stack frame or different goroutine is
selected, the scope shown in the VARIABLE section will be updated for the newly
selected stack frame, and the expressions in the WATCH section will be
automatically reevaluated relative to the newly selected stack frame.
1. Goroutine stacks are annotated with their internal goroutine IDs.
2. The current goroutine is marked with `*`. If multiple goroutines stop (e.g.
hit breakpoints) concurrently, Delve will pick one randomly. There also might
not be a current goroutine (e.g. deadlock, pause or internal breakpoint hit
by a system thread not running a goroutine).
3. If you click a goroutine call stack from the CALL STACK section, the
goroutine is _selected_.
4. You can select a frame of the selected goroutine. The VARIABLE and WATCH
sections will be updated accordingly and the cursor in the editor will be
moved to the corresponding location in the source code.
5. Runtime stack frames are deemphasized (greyed out or collapsed).
6. Thread IDs are shown for scheduled goroutines.
7. Stop reason. It’s possible that there are multiple reasons goroutines were
stopped, but currently only one reason is presented.
8. File name and line number of the frame.
9. You can trigger a debug action with the selected goroutine. Note: Resuming or
stopping only a single goroutine (Go Issue
[25578](https://github.com/golang/go/issues/25578),
[31132](https://github.com/golang/go/issues/31132)) is currently not
supported, so the action will cause all the goroutines to get activated or
paused.
10. Function name of the frame.
When the program stops due to exception, panic, or bad access error, the CALL
STACK shows the stop reason and the editor highlights the source location with
more details.

## `dlv` command from DEBUG CONSOLE
DEBUG CONSOLE accepts commands that allow users to dynamically inspect/change
debug configuration, or inspect the list of source code compiled in the debugged
binary. Use `dlv help` and `dlv config -list` from the DEBUG CONSOLE panel to
see the list of supported commands and dynamically adjustable settings.
## Configuration
### Launch.json attributes
There are many attributes that you can adjust in the launch and attach debug
configuration. The following general attributes are mandatory for all launch
configurations.
* `name`: the name of your configuration as it appears in the drop-down in the
Run view.
* `type`: the debugging type VS Code uses to decide which debugging extension
should be used. Always leave this set to `"go"`.
* `request`: `launch` or `attach`.
Here is the list of attributes specific to Go debugging.
| Property | Launch | Attach |
| --- | --- | --- |
| `args` | Command line arguments passed to the debugged program.
(Default: `[]`)
| _n/a_ |
| `asRoot` | (Experimental) Debug with elevated permissions (on Unix). It requires `integrated` or `external` console modes and is ignored in remote debugging.
(Default: `false`)
| (Experimental) Debug with elevated permissions (on Unix). This requires `integrated` or `external` console modes and is ignored in remote debugging.
(Default: `false`)
|
| `backend` | Backend used by delve. Maps to `dlv`'s `--backend` flag.
Allowed Values: `"default"`, `"native"`, `"lldb"`, `"rr"`
|
_same as Launch_|
| `buildFlags` | Build flags, to be passed to the Go compiler. Maps to dlv's `--build-flags` flag.
(Default: `[]`)
| _n/a_ |
| `console` | (Experimental) Where to launch the debugger and the debug target: internal console, integrated terminal, or external terminal. It is ignored in remote debugging.
Allowed Values: `"internalConsole"`, `"integratedTerminal"`, `"externalTerminal"`
(Default: `internalConsole`)
| (Experimental) Where to launch the debugger: internal console, integrated terminal, or external terminal. This does not affect tty of the running program. It is ignored in remote debugging.
Allowed Values: `"internalConsole"`, `"integratedTerminal"`, `"externalTerminal"`
(Default: `internalConsole`)
|
| `coreFilePath` | Path to the core dump file to open. For use on 'core' mode only
(Default: `""`)
|
_n/a_ |
| `cwd` | Workspace relative or absolute path to the working directory of the program being debugged if a non-empty value is specified. The `program` folder is used as the working directory if `cwd` is omitted or empty.
(Default: `""`)
| Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace.
(Default: `"${workspaceFolder}"`)
|
| `debugAdapter` | Select which debug adapter to use with this launch configuration.
Allowed Values: `"legacy"`, `"dlv-dap"`
(Default: `dlv-dap`)
|
_same as Launch_|
| `dlvFlags` | Extra flags for `dlv`. See `dlv help` for the full list of supported. Flags such as `--log-output`, `--log`, `--log-dest`, `--api-version`, `--output`, `--backend` already have corresponding properties in the debug configuration, and flags such as `--listen` and `--headless` are used internally. If they are specified in `dlvFlags`, they may be ignored or cause an error.
| _same as Launch_|
| `env` | Environment variables passed to the launched debuggee program. Format as string key:value pairs. Merged with `envFile` and `go.toolsEnvVars` with precedence `env` > `envFile` > `go.toolsEnvVars`.
| _n/a_ |
| `envFile` | Absolute path to a file containing environment variable definitions, formatted as string key=value pairs. Multiple files can be specified by provided an array of absolute paths. Merged with `env` and `go.toolsEnvVars` with precedence `env` > `envFile` > `go.toolsEnvVars`.
| _n/a_ |
| `followExec` | (Experimental) Enables or disables follow exec mode.
(Default: `false`)
| _n/a_ |
| `followExecRegex` | (Experimental) Regular expression. Only child processes with a command line that matches this regular expression will be followed during 'target follow-exec'.
(Default: `""`)
| _n/a_ |
| `goroutineFilters` | Configures which system goroutines should be shown in the call stack. See https://github.com/go-delve/delve/blob/master/Documentation/cli/README.md#goroutines
(Default: `""`)
| _same as Launch_|
| `hideSystemGoroutines` | Boolean value to indicate whether system goroutines should be hidden from call stack view.
(Default: `false`)
| _same as Launch_|
| `host` | When applied to remote-attach configurations, will look for "dlv ... --headless --listen=:" server started externally. In dlv-dap mode this will apply to all other configurations as well. The extension will try to connect to an external server started with "dlv dap --listen=:" to ask it to launch/attach to the target process.
(Default: `"127.0.0.1"`)
| When applied to remote-attach configurations, will look for "dlv ... --headless --listen=:" server started externally. In dlv-dap mode, this will apply to all other configurations as well. The extension will try to connect to an external server started with "dlv dap --listen=:" to ask it to launch/attach to the target process.
(Default: `"127.0.0.1"`)
|
| `logDest` | dlv's `--log-dest` flag. See `dlv log` for details. Number argument is not allowed. Supported only in `dlv-dap` mode, and on Linux and Mac OS.
| dlv's `--log-dest` flag. See `dlv log` for details. Number argument is not allowed. Supported only in `dlv-dap` mode and on Linux and Mac OS.
|
| `logOutput` | Comma separated list of components that should produce debug output. Maps to dlv's `--log-output` flag. Check `dlv log` for details.
Allowed Values: `"debugger"`, `"gdbwire"`, `"lldbout"`, `"debuglineerr"`, `"rpc"`, `"dap"`
(Default: `"debugger"`)
|
_same as Launch_|
| `mode` | One of `auto`, `debug`, `test`, `exec`, `replay`, `core`. In `auto` mode, the extension will choose either `debug` or `test` depending on active editor window.
Allowed Values: `"auto"`, `"debug"`, `"test"`, `"exec"`, `"replay"`, `"core"`
(Default: `auto`)
| Indicates local or remote debugging. Local is similar to the `dlv attach` command, remote - to `dlv connect`
Allowed Values: `"local"`, `"remote"`
(Default: `local`)
|
| `output` | Output path for the binary of the debugee.
(Default: `"debug"`)
|
_n/a_ |
| `port` | When applied to remote-attach configurations, will look for "dlv ... --headless --listen=:" server started externally. In dlv-dap mode this will apply to all other configurations as well. The extension will try to connect to an external server started with "dlv dap --listen=:" to ask it to launch/attach to the target process.
(Default: `2345`)
| When applied to remote-attach configurations, will look for "dlv ... --headless --listen=:" server started externally. In dlv-dap mode, this will apply to all other configurations as well. The extension will try to connect to an external server started with "dlv dap --listen=:" to ask it to launch/attach to the target process.
(Default: `2345`)
|
| `processId` | _n/a_ |
Option 1: Use process picker to select a process to attach, or Process ID as integer.
Allowed Values: `"${command:pickProcess}"`, `"${command:pickGoProcess}"`
Option 2: Attach to a process by name. If more than one process matches the name, use the process picker to select a process.
Option 3: The numeric ID of the process to be debugged. If 0, use the process picker to select a process.
(Default: `0`)
|
| `program` | Path to the program folder (or any go file within that folder) when in `debug` or `test` mode, and to the pre-built binary file to debug in `exec` mode. If it is not an absolute path, the extension interprets it as a workspace relative path.
(Default: `"${workspaceFolder}"`)
|
_n/a_ |
| `remotePath` | _n/a_ | (Deprecated) *Use `substitutePath` instead.*
The path to the source code on the remote machine, when the remote path is different from the local machine. If specified, becomes the first entry in substitutePath. Not supported with `dlv-dap`.
(Default: `""`)
|
| `showGlobalVariables` | Boolean value to indicate whether global package variables should be shown in the variables pane or not.
(Default: `false`)
| _same as Launch_|
| `showLog` | Show log output from the delve debugger. Maps to dlv's `--log` flag.
(Default: `false`)
| _same as Launch_|
| `showPprofLabels` | Configures which pprof lables to show as the goroutine name in the threads view
| _same as Launch_|
| `showRegisters` | Boolean value to indicate whether register variables should be shown in the variables pane or not.
(Default: `false`)
| _same as Launch_|
| `stackTraceDepth` | Maximum depth of stack trace collected from Delve.
(Default: `50`)
| _same as Launch_|
| `stderrTo` | Writes the program's standard error to a file
(Default: `""`)
| _n/a_ |
| `stdinFrom` | Reads the program's standard input from a file
(Default: `""`)
| _n/a_ |
| `stdoutTo` | Writes the program's standard output to a file
(Default: `""`)
| _n/a_ |
| `stopOnEntry` | Automatically stop program after launch.
(Default: `false`)
| Automatically stop program after attach.
(Default: `false`)
|
| `substitutePath` | An array of mappings from a local path (editor) to the remote path (debugee). This setting is useful when working in a file system with symbolic links, running remote debugging, or debugging an executable compiled externally. The debug adapter will replace the local path with the remote path in all of the calls.
- `"from"`: The absolute local path to be replaced when passing paths to the debugger.
(Default: `""`)
- `"to"`: The absolute remote path to be replaced when passing paths back to the client.
(Default: `""`)
| An array of mappings from a local path (editor) to the remote path (debugee). This setting is useful when working in a file system with symbolic links, running remote debugging, or debugging an executable compiled externally. The debug adapter will replace the local path with the remote path in all of the calls. Overridden by `remotePath`.
- `"from"`: The absolute local path to be replaced when passing paths to the debugger.
(Default: `""`)
- `"to"`: The absolute remote path to be replaced when passing paths back to the client.
(Default: `""`)
|
| `trace` | Various levels of logging shown in the debug console & 'Go Debug' output channel. When using the `legacy` debug adapter, the logs will also be written to a file if it is set to a value other than `error`.
Allowed Values: `"verbose"`, `"trace"`, `"log"`, `"info"`, `"warn"`, `"error"`
(Default: `"error"`)
|
_same as Launch_|
| `traceDirPath` | Directory in which the record trace is located or to be created for a new output trace. For use on 'replay' mode only
(Default: `""`)
| _n/a_ |
| `waitFor` | _n/a_ | Wait for a process with a name beginning with the given prefix
(Default: `""`)
|
⚠️ Delve resolves relative paths from `dlv dap` process's working directory, but
from which directory the extension spawns the `dlv dap` process is an
implementation detail. Thus, use
[the VS Code variables substitution](https://code.visualstudio.com/docs/editor/variables-reference)
to ensure consistent expansion of paths. VS Code will resolve the variables
inside strings in `launch.json` before passing the configuration to the Go
extension and `dlv dap`. For example, `${workspaceFolder}` will be replaced with
the absolute path to the workspace root folder. When appropriate, the Go
extension will resolve relative paths or home directory (~) before sending the
configuration to `dlv dap`.
### Debug symlink directories
Since the debugger and go compiler use the actual filenames, extra configuration
is required to debug symlinked directories. Use the `substitutePath` property to
tell the `debugAdapter` how to properly translate the paths. For example, if
your project lives in `/path/to/actual/helloWorld`, but the project is open in
vscode under the linked folder `/link/to/helloWorld`, you can add the following
to your config to set breakpoints in the files in `/link/to/helloWorld`:
```json
{
"name": "Launch with symlinks",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "/path/to/actual/helloWorld",
"substitutePath": [
{
"from": "/link/to/helloWorld",
"to": "/path/to/actual/helloWorld"
}
]
}
```
### Settings
You can adjust the default value of the following configuration properties using
`go.delveConfig` settings. These default values are useful when you choose to
run a debug session without the launch configuration set in `launch.json`. For
example, debug sessions started using the `Debug Test` code lenses use the
adjusted values from these settings.
* [`go.delveConfig`](settings.md#go.delveConfig)
* `debugAdapter`: Controls which debug adapter to use (default: `legacy`).
Select ‘dlv-dap’.
* `showGlobalVariables`: Show global variables in the Debug view (default:
`false`).
* `substitutePath`: Path mappings to apply to get from a path in the editor to
a path in the compiled program (default: `[]`).
⚠️ Where is the `dlvLoadConfig` setting? Delve debugger imposes variable loading
limits to avoid loading too many variables at once and negatively impacting
debugging latency. The legacy adapter supported `dlvLoadConfig` to adjust these
limits for the duration of the session. The user therefore had to come up with a
one-size-fits-all limit if the default behavior was not satisfactory. `dlv-dap`
mode uses a different approach as described in
[the Data Inspection section](#data-inspection). If this setting is configured
and `dlv-dap` mode is used, the extension will show a warning prompt now. If the
current variable loading behavior and internal limits are not working for you,
please [open an issue](https://github.com/golang/vscode-go/issues/new) and share
your feedback.
## Advanced topics
### Go debug extension architecture overview
VS Code implements a generic, language-agnostic debugger UI based on
[Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/)
(DAP), an abstract protocol for communicating with debugger backend. Previously,
the Go extension used an intermediary typescript program (legacy debug adapter)
to launch Delve and adapt Delve to DAP. With
[the new, native DAP implementation in Delve](https://github.com/go-delve/delve/tree/master/service/dap),
the intermediary program is no longer necessary, and efficient and tight
integration with Delve becomes possible.
For information on debugging using the legacy debug adapter, please see the old
[Debugging Documentation](debugging.md). Note that many new or enhanced features
discussed in this document may not be available with the legacy debug adapter.
### Handling STDIN
The Go extension and `dlv` started as a subprocess of the extension do not have
access to `tty`. The Go extension captures and forwards STDOUT/STDERR of the
debug program to VS Code, so they can appear in `DEBUG OUTPUT` panel. But this
arrangement does not handle STDIN.
When the target program needs to read from STDIN or access terminals (`tty`),
use the `"console"` launch option that controls where the `dlv` debugger and the
target process run:
* `integratedTerminal` for the terminal inside VS Code
* `externalTerminal` for the terminal outside VS Code
The Go extension delegates interaction with terminals to VS Code
[using Debug Adapter Protocol's `RunInTerminal` functionality](https://github.com/golang/vscode-go/discussions/1626).
For configuring VS Code's terminal related behavior, see VS Code's
[documentation](https://code.visualstudio.com/docs/editor/integrated-terminal).
### Debug programs and tests as root
In order to run and debug a program or a package test running as root, the
debugger (`dlv`) must run with root privilege, too. You can start the debug
session with root privilege utilizing the `"asRoot"` AND `"console"` launch
options. This is currently supported only on Linux and Mac.
When `asRoot` is true, the Go extension will use the `sudo` command to run
`dlv`. Since `sudo` may ask you to enter password, the debug session needs
[terminal access](#handling-stdin) so set `"console": "integratedTerminal"` or
`"console": "externalTerminal"` in the launch configuration.
#### Debug a program as root
For example, the following launch configuration will start `myprogram` and debug
it by running `sudo dlv dap` command in the integrated terminal.
```json
{
"name": "Launch as Root",
"request": "launch",
"mode": "exec",
"asRoot": true,
"program": "${workspaceRoot}/myprogram",
"console": "integratedTerminal",
...
}
```
The `asRoot` setting can be used with `auto`/`test`/`debug` launch modes that
**build** the target binary to debug. That means the `go` command will be
invoked as root to compile the binary, too. This can cause issues:
* by default, `sudo` does not preserve the user's current environment variables
(see documentations about sudo's `--preserve-env` option). For example, `PATH`
or library paths required for build may be different.
* Go environment variable settings usually associated in the home directory are
different.
* Module/build caches used during build as root may be different from the caches
used in your normal build. If they are the same, you may encounter permission
errors due to cache data written to the caches as root.
Instead, you can arrange the `exec` launch mode to work with a pre-launch
[task](https://code.visualstudio.com/docs/editor/tasks).
First, configure a debug build task to compile the target binary.
In `.vscode/tasks.json`:
```json
{
...
"tasks": [
{
"label": "go: build (debug)",
"type": "shell",
"command": "go",
"args": [
"build",
"-gcflags=all=-N -l",
"-o",
"${fileDirname}/__debug_bin"
],
"options": {
"cwd": "${fileDirname}"
},
...
}
]
}
```
The `-gcflags=all=-N -l` flag tells the `go build` command to preserve the debug
information. The `-o` flag causes the compiled binary to be placed in
`"${fileDirname}/__debug_bin"`. Extra build flags and environment variables
_used for build_ should be configured here as `args` or `options`'s `env`
settings.
It might be useful to add `__debug_bin` to your `.gitignore` to avoid debugging
binaries getting checked-in into your repository.
Then, configure the launch config to run the task before starting debugging.
In `.vscode/launch.json`:
```json
...
"configurations": [
{
"name": "Launch Package as root",
"type": "go",
"request": "launch",
"mode": "exec",
"asRoot": true,
"console": "integratedTerminal",
"program": "${fileDirname}/__debug_bin",
"preLaunchTask": "go: build (debug)",
}
]
```
Settings (`args`, `cwd`, `env`, ...) configured in the above `launch.json` will
only apply when _running_ the compiled binary, not when building the binary.
#### Debug a package test as root
To debug package tests as root add the following launch and task configurations.
In `.vscode/tasks.json`:
```json
...
"tasks": [
{
...
},
{
"label": "go test (debug)",
"type": "shell",
"command": "go",
"args": [
"test",
"-c",
"-o",
"${fileDirname}/__debug_bin"
],
"options": {
"cwd": "${fileDirname}",
},
...
}
]
```
In `.vscode/launch.json`:
```json
...
"configurations": [
{
...
},
{
"name": "Debug Package Test as root",
"type": "go",
"request": "launch",
"mode": "exec",
"asRoot": true,
"program": "${fileDirname}/__debug_bin",
"cwd": "${fileDirname}",
"console": "integratedTerminal",
"preLaunchTask": "go test (debug)"
}
]
```
### Manually install `dlv`
On rare occasions, you may want to install `dlv` by yourself instead of letting
the extension handle its installation.
First, find where the Go extension finds tools. Like
[other tools the extension uses](tools.md#tools), the Go extension searches the
`dlv` executable from `${GOPATH}/bin`, `${GOBIN}` and `${PATH}` (or `Path` in
Windows). So, install `dlv` in the directory. The easiest way to check the tool
installation location the Go extension uses is currently by running the
`Go: Locate Configured Go Tools` command from the command palette (⇧+⌘+P or
Ctrl+Shift+P).
If your Go version is 1.16 or newer:
```
GOBIN= go install github.com/go-delve/delve/cmd/dlv@latest
```
If your Go version is older than 1.16:
```
cd $(mktemp -d)
GO111MODULE=on GOBIN= go get github.com/go-delve/delve/cmd/dlv@latest
```
You can choose to install a different version of `dlv` by specifying a specific
commit hash, a branch name (e.g. `master`), or a released version instead of
`latest`. For more details about manual installation, see
[Delve's documentation](https://github.com/go-delve/delve/tree/master/Documentation/installation).
If you want to explicitly specify the location of the delve binary, use the
`go.alternateTools` setting:
```json5
"go.alternateTools": {
"dlv": ""
}
```
### Remote debugging
> If you are able to use the
> [Remote Development](https://aka.ms/vscode-remote/download/extension)
> extensions and VS Code’s universal
> [remote development capabilities](https://code.visualstudio.com/docs/remote/remote-overview),
> that is the recommended way to debug Go programs remotely. Check out
> [Getting started](https://code.visualstudio.com/docs/remote/remote-overview#_getting-started)
> section and
> [Remote tutorials](https://code.visualstudio.com/docs/remote/remote-overview#_remote-tutorials)
> to learn more.
Remote debugging is the debug mode commonly used to work with a debugger and
target running on a remote machine or a container. In spite of its name, it can
also be used on a local machine with server started in an external terminal
(e.g. to support entering stdin into the server's terminal window).
With the introduction of `dlv dap` users now have two options for remote (i.e.
external) debugging.
#### Connect to headless delve with target specified at server start-up
In this mode the user must first manually start a
[`dlv --headless`](https://github.com/go-delve/delve/tree/master/Documentation/api)
server listening at `host:port` while specifying the target program to
debug/test/exec or a process to attach to on the command-line. A
[remote attach](#attach) configuration is then used to connect to the debugger
with a running target.
The
[headless dlv server](https://github.com/go-delve/delve/tree/master/Documentation/api)
can now be used with both `"debugAdapter": "legacy"` (default value) and
`"debugAdapter": "dlv-dap"` (with Delve v1.7.3 or newer) as well as Delve's
[command-line interface](https://github.com/go-delve/delve/tree/master/Documentation/cli)
via `dlv connect`. The `--accept-multiclient` flag makes this a multi-use server
that persists on `Disconnect` from a client and allows repeated connections from
any of the aforementioned clients. A combination of
`--accept-multiclient --continue` flags can be used to resume process execution
on start-up. Please see `dlv --help` and `dlv [command] --help` for dlv's
command-line options.
We encourage you to give the newly added `"debugAdapter": "dlv-dap"` support a
try and to
[let us know of any issues](https://github.com/golang/vscode-go/issues/new). If
you need to use the `legacy` mode, please also see the
[legacy remote debugging](debugging-legacy.md#remote-debugging) documentation.
For example, start external headless server:
```
dlv debug /path/to/program/ --headless --listen=:12345 # also add as needed: --accept-multiclient --continue
```
Connect to it with a remote attach configuration in your `launch.json`:
```json5
{
"name": "Connect to external session",
"type": "go",
"debugAdapter": "dlv-dap", // `legacy` by default
"request": "attach",
"mode": "remote",
"port": 12345,
"host": "127.0.0.1", // can skip for localhost
"substitutePath": [
{ "from": "${workspaceFolder}", "to": "/path/to/remote/workspace" },
...
]
}
```
#### Connect to delve dap with target specified at client start-up
In this mode the user must first manually start a
[`dlv dap` server](https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_dap.md)
listening at `host:port` and then specify the target program via
[launch](#launch) or [attach](#attach) client config with a `"port"` attribute.
Instead of starting a new local server, the Go extension will tell VS Code to
connect to the server specified by `host:port` attributes and then send a
request with the target to debug. This option provides the flexibility of easily
adapting local configurations to connect to external servers, but ⚠️ must be
used with care since anyone who can connect to the server can make it run
arbitrary programs.
When using `launch` mode, the `program` attribute must point to the absolute
path of the package or binary to debug in the remote host’s file system even
when `substitutePath` is specified. When using `attach` mode outside of local
host, you need to specify the `processId` in the config since
[the processId resolution feature](#attach) cannot gather information about
processes running remotely.
Start a `dlv dap` server ready to accept a client request to launch or attach to
a target process:
```
dlv dap --listen=:12345
```
Use the following `launch` configuration to tell `dlv` to execute a binary
precompiled with `go build -gcflags=all="-N -l"`:
```json5
{
"name": "Connect and launch",
"type": "go",
"debugAdapter": "dlv-dap", // the default
"request": "launch",
"port": 12345,
"host": "127.0.0.1", // can skip for localhost
"mode": "exec",
"program": "/absolute/path/to/remote/workspace/program/executable",
"substitutePath": [
{ "from": "${workspaceFolder}", "to": "/path/to/remote/workspace" },
...
]
}
```
Or have the binary compiled by `dlv dap` by modifying the above configuration to
use:
```json5
"mode": "debug",
"program": "/absolute/path/to/remote/workspace/package",
```
⚠️ Limitations
* Unlike `dlv --headless` above, `dlv dap` does not support
`--accept-multiclient` or `--continue` flags, which means after a debug
session ends, the `dlv dap` process will always exit.
* If you use `debug` or `test` mode `launch` requests, Delve builds the target
binary. Delve tries to build the target from the directory where the `dlv`
process is running, so make sure to run the `dlv` command from the directory
you would run the `go build` or `go test` command.
### Run debugee externally
Sometimes you might like to launch the program for debugging outside of VS Code
(e.g. as a workaround of the missing `console` support to enter stdin via an
external terminal or separate target's output from debug session logging). There
are currently two options:
* Compile and run the target program from the external terminal and use
[the "attach" configuration](#attach).
* Run the debug server from the external terminal with `--listen=:` and
have VS Code connect to it using `port` in your launch configuration (see
["Remote Debugging"](#remote-debugging) for more details)
## Troubleshooting
The suggestions below are intended to help you troubleshoot any problems you
encounter. If you are unable to resolve the issue, please take a look at the
[current known debugging issues](https://github.com/golang/vscode-go/issues?q=is%3Aissue+is%3Aopen+label%3ADebug)
or [report a new issue](#reporting-issues).
1. Read documentation and [FAQs](#faqs). Also check the
[Delve FAQ](https://github.com/go-delve/delve/blob/master/Documentation/faq.md)
in case the problem is mentioned there.
1. Check your `launch.json` configuration. Often error messages appearing in the
DEBUG CONSOLE panel reveal issues.
1. Update Delve (`dlv`) to pick up most recent bug fixes. Follow
[the instruction](debugging.md#staying-up-to-date).
1. Check if you can reproduce the issue with `dlv`, the command line tool from
the integrated terminal. If it's reproducible when
using `dlv`, take a look at the
[Delve project issue tracker](https://github.com/go-delve/delve/issues).
1. Capture [logs](debugging.md#collecting-logs) and inspect them.
1. Look at the
[existing debugging issues](https://github.com/golang/vscode-go/labels/Debug)
if similar issues were reported.
1. If none of these solve your problem, please
[open a new issue](#reporting-issues).
## FAQs
### I need to view large strings. How can I do that if `dlvLoadConfig` with `maxStringLen` is deprecated?
The legacy adapter used `dlvLoadConfig` as one-time session-wide setting to
override dlv's conservative default variable loading limits, intended to protect
tool's performance. The new debug adapter is taking a different approach with
on-demand loading of composite data and updated string limits, relaxed when
interacting with individual strings. In particular, if the new default limit of
512, applied to all string values in the variables pane, is not sufficient, you
can take advantage of a larger limit of 4096 with one of the following:
* Hover over the variable in the source code
* `Copy as Expression` to query the string via REPL in the DEBUG CONSOLE panel
* `Copy Value` to clipboard
Please [open an issue](https://github.com/golang/vscode-go/issues/new) if this
is not sufficient for your use case or if you have any additional feedback.
### Why does my debug session have an `invalid command` error when I try to step?
When stepping through a program on a particular goroutine, the debugger will
make sure that the step is completed, even when interrupted by events on a
different goroutine. If a breakpoint is hit on a different goroutine, the debug
adapter will stop the program execution to allow you to inspect the state, even
though the step request is still active.
If you attempt to make another step request you will get an `invalid command`
error.
Use `Continue` to resume program execution.
If you do not want the step request to be interrupted, you can disable all
breakpoints from VS Code from the context menu in the `Breakpoints` view.
### My program does not stop at breakpoints
Check the "BREAKPOINTS" section in the debug view and see if the breakpoints are
[greyed out](https://code.visualstudio.com/docs/editor/debugging#_breakpoints)
when your debug session is active. Setting `stopOnEntry` is a great way to pause
execution at the start to _verify_ breakpoints are set correctly. Or
[enable logging](#collecting-logs) and see if `setBreakpoints` requests
succeeded with all the breakpoints _verified_.
This problem often occurs when the source location used in compiling the
debugged program and the workspace directory VS Code uses are different. Common
culprits are remote debugging where the program is built in the remote location,
use of symbolic links, or use of `-trimpath` build flags. In this case,
configure the `substitutePath` attribute in your launch configuration.
#### Trimpath tips
If you are using `-trimpath` to build your program, you need to add entries to substitute
path to let the debugger know how to map the package paths that are compiled in the
binary to the files that you are looking at in the editor.
Here are some tips for configuring substitutePath. This assumes that your program is using module mode, which is the default.
One rule that you will need will map your main module. The mapping will map `"from"` the file path to the directory containing the module, `"to"` the module path.
You will also need to create a similar mapping for all dependencies. These include modules
in the module cache, vendored modules, and the standard library.
```json
"substitutePath": [
// Main module.
{
"from": "${workspaceFolder}",
"to": "moduleName",
},
// Module cache paths.
{
"from": "${env:HOME}/go/pkg/mod/github.com",
"to": "github.com",
},
{
"from": "${env:HOME}/go/pkg/mod/golang.org",
"to": "golang.org",
},
...
// Standard library paths.
// This rule should come last since the empty "to" will match every path.
{ "from": "/path/to/local/goroot/pkg" , "to": ""}
],
```
Since rules are applied both from client to server and server to client,
rules with an empty string will be applied to _all_ paths that it sees, so even
dependencies will be mapped to `"/path/to/module"`.
We plan to make this easier in the future. Progress can be tracked
in the issue tracker [golang/vscode-go#1985](https://github.com/golang/vscode-go/issues/1985).
### Debug sessions started with the "debug test" CodeLens or the test UI does not use my `launch.json` configuration
The "debug test" CodeLens and the [test UI](features.md#test-and-benchmark) do
not use the `launch.json` configuration
([Issue 855](https://github.com/golang/vscode-go/issues/855)). As a workaround,
use the `go.delveConfig` setting and the `go.testFlags` setting. Please note
that these all apply to all debug sessions unless overwritten by a specific
`launch.json` configuration.
### Starting a debug session fails with
`decoding dwarf section info at offset 0x0: too short` or
`could not open debug info` error
These errors indicate that your binary was built with linker flags that stripped
the symbol table (`-s`) or the DWARF debug information (`-w`), making debugging
impossible. If the binary is built while launching the session, make sure your
`launch.json` configuration does not contain
`"buildFlags": "--ldflags '-s -w'"`. If you use `debug test` or Test Explorer,
check `go.buildFlags` in `settings.json`. If the binary is built externally,
check the command-line flags and do not use `go run`. Unlike `go build`,
`go run` passes `-s -w` to the linker under the hood. If you try to attach to
such a binary with a debugger, it will fail with one of the above errors (see Go
Issue [24833](https://github.com/golang/go/issues/24833)). Instead let dlv build
the binary for you or use `go build -gcflags=all="-N -l"`.
## Report issues
When you are having issues in `dlv-dap` mode, first check if the problems are
reproducible after updating `dlv` and using the most recent version of `dlv`.
It's possible that the problems are already fixed. You can also try to install
`dlv` at tree head. Follow the instruction for
[updating `dlv`](#staying-up-to-date) and
[updating extension](https://code.visualstudio.com/docs/editor/extension-gallery#\_extension-autoupdate).
Please report issues in
[our issue tracker](https://github.com/golang/vscode-go/issues) with the
following information.
* `go version`
* `go version -m `
* VS Code and VS Code Go version (e.g. `code --version`)
* Instructions to reproduce the issue (code snippets, your `launch.json`, screenshot)
* DAP trace (See [the instruction](#collecting-logs))
### Collect logs
```json5
{
"name": "Launch file",
"type": "go",
"trace": "verbose",
"showLog": true,
"logOutput": "dap",
...
}
```
The `logOutput` and `showLog` attributes in `launch.json` enable Delve-side
logging (server-side) and DAP message tracing. The `trace` attribute controls
the verbosity of Go extension's side logging (client-side).
The logging will appear in the `Go Debug` output channel (Command Palette ->
"View: Toggle Output" -> Select "Go Debug" from the dropdown menu). By nature,
debug logs may contain sensitive information. Please review the logs carefully
before sharing debug logs.
## Development
### Code location
The core part of Delve DAP implementation is in the
[`service/dap`](https://github.com/go-delve/delve/tree/master/service/dap)
package. Follow Delve project's
[contribution guideline](https://github.com/go-delve/delve/blob/master/CONTRIBUTING.md#contributing-code)
to send PRs.
Code for integration with the Go extension is mostly in
[`src/goDebugFactory.ts`](https://github.com/golang/vscode-go/blob/master/extension/src/goDebugFactory.ts)
and tests are in
[`test/integration/goDebug.test.ts`](https://github.com/golang/vscode-go/blob/master/extension/test/integration/goDebug.test.ts).
Please take a look at VS Code Go project's
[contribution guideline](contributing.md) to learn about how to prepare a change
and send it for review.
### Testing
For simple launch cases, build the `dlv` binary, and configure
`"go.alternateTools"` setting.
```json5
"go.alternateTools": {
"dlv":
}
```

If you are having issues with seeing logs and/or
suspect problems in the extension's integration, you can start the Delve DAP
server from a separate terminal and configure the extension to directly connect
to it. Please remember to
[file an issue](https://github.com/golang/vscode-go/issues/new) if you encounter
any logging-related problems.
```
dlv dap --listen=:12345 --log --log-output=dap
```
```json5
{
"name": "Launch file",
"type": "go",
"request": "launch",
"debugAdapter": "dlv-dap",
...
"port": 12345
}
```
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/experiments.md
# Experiments
Pre-release versions of [vscode-go][vscode-go] include experimental features.
These features may be individually enabled or disabled via the setting
`go.experiments`.
[vscode-go]: https://github.com/golang/vscode-go/blob/master/README.md#pre-release-versions
## Test explorer
[Go Companion][exp-vscode-go] includes an experimental test explorer
implementation based on `gopls`'s test discovery. This requires gopls v0.17.0 or
newer. If Go Companion is present and vscode-go is a pre-release version,
vscode-go will prefer Go Companion's test explorer, disabling its own, unless
the experiment is set to `off`. The experimental test explorer provides more
robust test discovery by using gopls, including static discovery of _some_
subtests. It also implements:
- Ignore tests within files excluded by `files.exclude` or
`goExp.testExplorer.exclude`.
- Disable automatic discovery of tests by setting `goExp.testExplorer.discovery`
to "off".
- Control how tests are displayed with `goExp.testExplorer.showFiles`,
`goExp.testExplorer.nestPackages`, and `goExp.testExplorer.nestSubtests`.
- Debugging a test updates its status in the test explorer.
- Support for continuous runs.
- Support for code coverage.
- Code lenses (hidden by default) that are integrated with the test explorer.
- Integrated viewer for pprof profiles.
[exp-vscode-go]: https://marketplace.visualstudio.com/items?itemName=ethan-reesor.exp-vscode-go
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/faq.md
# Frequently Asked Questions
**NOTE: [Debugging](debugging.md#faqs) has its own FAQ documentation.**
## Syntax highlighting doesn't seem to work.
The default syntax highlighting for Go files is provided by a
[TextMate rule](https://github.com/worlpaker/go-syntax) embedded in VS Code,
not by this extension.
For accurate syntax highlighting (including generics support), we recommend enabling
[semantic highlighting](https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide)
by turning on [Gopls' `ui.semanticTokens` setting](settings.md#uisemantictokens).
```json
"gopls": { "ui.semanticTokens": true }
```
If you are experiencing issues with syntax highlighting, first check if you
are using semantic highlighting. In case you did not enable semantic highlighting,
report the issues to the [go-syntax](https://github.com/worlpaker/go-syntax)
project directly.
## Code formatting by this extension doesn't seem to work.
When you have multiple formatter extensions, be sure to set this
extension as the default formatter for go language.
```json5
"[go]": {
"editor.defaultFormatter": "golang.go"
}
```
## How can I stop the extension from formatting files on save?
Formatting and organizing imports for Go are enabled by default. This is implemented
by setting the [language-specific editor settings](https://code.visualstudio.com/docs/getstarted/settings#_languagespecific-editor-settings), that take precedence
over user/workspace editor settings.
You can choose to disable them by configuring the following settings.
```json5
"[go]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.organizeImports": false
}
}
```
This decision was made a while ago to help users follow the best practice,
and to detect broken code early (e.g. unused imports causes compile errors in Go).
Unfortunately, these language-specific editor settings overriden by the
extension is not easily visible from the settings UI, and confuses users new to Go.
In the following issues, we are discussing and collecting ideas to improve
the situation without interrupting existing users.
* [`editor.formatOnSave` and `editor.codeActionsOnSave`](https://github.com/golang/vscode-go/issues/1815)
* [`editor.suggest.snippetsPreventQuickSuggestions`](https://github.com/golang/vscode-go/issues/1805)
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/features.md
# Features
This document describes the features supported by this extension.
## Table of Contents
* [IntelliSense](#intellisense)
* [Code completion](#code-completion)
* [Signature help](#signature-help)
* [Quick info on hover](#quick-info-on-hover)
* [Code Navigation](#code-navigation)
* [Go to definition](#go-to-definition)
* [Go to symbol](#go-to-symbol)
* [Find references](#find-references)
* [Find interface implementations](#find-interface-implementations)
* [Document outline](#document-outline)
* [Toggle between code and tests](#toggle-between-code-and-tests)
* [Syntax Highlighting](#syntax-highlighting)
* [Inlay Hints](#inlay-hints)
* [Code Editing](#code-editing)
* [Snippets](#snippets)
* [Format and organize imports](#format-and-organize-imports)
* [Add import](#add-import)
* [Rename symbol](#rename-symbol)
* [Refactor](#refactor)
* [Code Generation](#code-generation)
* [Add or remove struct tags](#add-or-remove-struct-tags)
* [Generate interface implementation](#generate-interface-implementation)
* [Generate unit tests](#generate-unit-tests)
* [Fill struct literals](#fill-struct-literals)
* [Diagnostics](#diagnostics)
* [Build errors](#build-errors)
* [Vet and extra analyses](#vet-and-extra-analyses)
* [Lint errors](#lint-errors)
* [Vulnerabilities in dependencies](#analyze-vulnerabilities-in-dependencies)
* [Code Lenses](#code-lenses)
* [Run and test in the editor](#run-and-test-in-the-editor)
* [Run your code](#run-your-code)
* [Test and benchmark](#test-and-benchmark)
* [Code coverage](#code-coverage)
* [Profiling](#profiling)
* [Debug your code](#debugging)
* [Other](#other)
* [Go Playground](#go-playground)
## [IntelliSense](https://code.visualstudio.com/docs/editor/intellisense)
### Code completion
Completion results appear for symbols as you type. You can trigger this manually with the Ctrl+Space shortcut.
Autocompletion is also supported for packages you have not yet imported into your program.
### Signature help
Information about the signature of a function pops up as you type in its parameters.
### Quick info on hover
Documentation appears when you hover over a symbol.
## [Code Navigation](https://code.visualstudio.com/docs/editor/editingevolved)
### Go to definition
Jump to or peek a symbol's declaration.
### Find references
Find or go to the references of a symbol.
This feature is not available if you are using Go modules **without** [`gopls`](gopls.md), the Go language server.
### Find interface implementations
Find the concrete types that implement a given interface.
This feature is not available if you are using Go modules **without** [`gopls`](gopls.md), the Go language server.
### [Go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-symbol)
Search for symbols in your file or workspace by opening the Command Palette (Ctrl+Shift+P) and typing `@` for symbols in the current file or `#` for symbols in the entire workspace.
### Call hierarchy
Show all calls from or to a function.
### Document outline
See all the symbols in the current file in the VS Code's [Outline view](https://code.visualstudio.com/docs/getstarted/userinterface#_outline-view).
### Toggle between code and tests
Quickly toggle between a file and its corresponding test file by using the [`Go: Toggle Test File`](commands.md#go-toggle-test-file) command.
## Syntax Highlighting
The default syntax highlighting for Go files is implemented in Visual Studio Code using TextMate grammar, not by this extension.
If you are using `gopls`, you can enable [Semantic Highlighting](https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide) for more accurate syntax highlighting based on semantic tokenization using this setting:
```
"gopls": {
"ui.semanticTokens": true,
// you can optionally turn on these features for more colors
// see https://go.dev/issue/45753 and https://go.dev/issue/45792
"ui.noSemanticString": true, // delegates string syntax highlighting to vscode
"ui.noSemanticNumber": true, // delegates number syntax highlighting to vscode
}
```
### Go template syntax highlighting
When `gopls`'s semantic tokens feature is enabled, `gopls` also provides semantic tokens for Go template files (language identifier: `gotmpl`). By default, the extension associates all `*.tmpl` or `*.gotmpl` files in the workspace with `gotmpl` language. Users can override the language mode by using Visual Studio Code's UI or the `"files.associations"` setting. See [Visual Studio Code's doc](https://code.visualstudio.com/docs/languages/overview#_changing-the-language-for-the-selected-file) for more details.
## Inlay Hints
Inlay hints render additional inline information to source code to help you understand what the code does.
They can be enabled/disabled with the `editor.inlayHints.enabled` setting in combination with `go.inlayHints` [settings](settings.md#go.inlayHints.assignVariableTypes) to enable inlay hints types.
### Variable types in assign statements
```go
i/* int*/, j/* int*/ := 0, len(r)-1
```
### Variable types in range statements
```go
for k/* int*/, v/* string*/ := range []string{} {
fmt.Println(k, v)
}
```
### Composite literal field names
```go
{/*in: */"Hello, world", /*want: */"dlrow ,olleH"}
```
### Composite literal types
```go
for _, c := range []struct {
in, want string
}{
/*struct{ in string; want string }*/{"Hello, world", "dlrow ,olleH"},
}
```
### Constant values
```go
const (
KindNone Kind = iota/* = 0*/
KindPrint/* = 1*/
KindPrintf/* = 2*/
KindErrorf/* = 3*/
)
```
### Function type parameters
```go
myFoo/*[int, string]*/(1, "hello")
```
### Parameter names
```go
parseInt(/* str: */ "123", /* radix: */ 8)
```
## Code Editing
### [Snippets](https://code.visualstudio.com/docs/editor/userdefinedsnippets)
Predefined snippets for quick coding. These snippets will appear as completion suggestions when you type. Users can also define their own custom snippets (see [Snippets in Visual Studio Code](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_create-your-own-snippets)).
### Format and organize imports
Format code and organize imports, either manually or on save.
The extension formats Go code, organizes imports, and removes unused imports by default. For different behavior, please override per-language default settings following [the instruction](advanced.md#formatting-code-and-organizing-imports).
#### Organizing imports
When organizing imports, the imported packages are grouped in the default `goimports` style. In order to group some packages after 3rd-party packages, use the [`"formatting.local"`](settings.md#formattinglocal) setting.
```json
"gopls": {
"formatting.local": "example.com/myorg,github.com/myorg2"
}
```
#### Add import
The extension organizes imports automatically and can add missing imports if the package is present in your module cache already. However, you can also manually add a new import to your file through the [`Go: Add Import`](commands.md#go-add-import) command. Available packages are offered from module cache (or from your `GOPATH` in GOPATH mode).
#### Custom formatter
In addition to the default [`go fmt`](https://pkg.go.dev/cmd/gofmt) style formatter, the language server (`gopls`) supports `github.com/mvdan/gofumpt` style formatting. Use gopls's [`formatting.gofumpt`](settings.md#formattinggofumpt) setting:
```json
"gopls": { "formatting.gofumpt": true }
```
You can also configure to use other custom formatter (`golines`) by using the `"go.formatTool"` setting. The custom formatter must operate on file contents from STDIN, and output the formatted result to STDOUT.
```json
"go.formatTools": "custom",
"go.alternateTools": {
// the binary name if it is in your PATH, or
// provide the exact path to your
// custom formatter.
"customFormatter": "golines"
}
```
### [Rename symbol](https://code.visualstudio.com/docs/editor/refactoring#_rename-symbol)
Rename all occurrences of a symbol in your workspace.
**Note**: For undo after rename to work on Windows, you need to have `diff` tool on your `PATH`.
This feature is not available if you are using Go modules **without** [`gopls`](gopls.md), the Go language server.
### Refactor
Select the area for refactoring (e.g. variable, function body, etc). Click on the Code Action light bulb icon
that appears in the selected area, or select "Refactoring..." or "Rename Symbol" from the VS Code Context menu.
For known issues with this feature see [golang/go#37170](https://github.com/golang/go/issues/37170).
## Code Generation
### Add or remove struct tags
Use the [`Go: Add Tags to Struct Fields`](commands.md#go-add-tags-to-struct-fields) command to automatically generate or remove [tags](https://pkg.go.dev/reflect?tab=doc#StructTag) for your struct. This feature is provided by the [`gomodifytags`](tools.md#gomodifytags) tool invoked via gopls.
### Generate interface implementation
Use the [`Go: Generate Interface Stubs`](commands.md#go-generate-interface-stubs) command to automatically generate method stubs for a given interface. This feature is provided by the [`impl`](tools.md#impl) tool.
### Generate unit tests
Easily generate unit tests for your project by running one of the [`Go: Generate Unit Tests for ...`](commands.md#go-generate-unit-tests-for-file) commands. This can be done at a function, file, or package level. This feature is provided by the [`gotests`](tools.md#gotests) tool.
### Fill struct literals
Use the [Code Action](https://code.visualstudio.com/docs/editor/refactoring#_code-actions-quick-fixes-and-refactorings) to automatically fill a struct literal with its default values. The Go language server provides this capability as a `refactor.rewrite` type code action.
**Note**: The old "Go: Fill struct" command was removed in v0.40.0 in favor of the Code Action.
## Diagnostics
The extension, powered by the Go language server (`gopls`), offers various diagnostics and analyses features,
and often with quick fixes to address detected issues.
### Build errors
Compile and type errors are shown as you type by default. This works not only Go source code, but also `go.mod`, `go.work`, and Go template files.
### Vet and extra analyses
The Go language server (`gopls`) reports [`vet`](https://pkg.go.dev/cmd/vet) errors and runs many useful analyzers as you type. A full list of analyzers that `gopls` uses can be found in the [analyses settings section](https://github.com/golang/vscode-go/wiki/settings#uidiagnosticanalyses).
### Lint errors
You can configure an extra linter to run on file save. This behavior is configurable through the [`"go.lintOnSave"`](settings.md#go.lintOnSave) setting.
The default lint tool is [`staticcheck`]. Popular alternative linters such as [`golint`], [`golangci-lint`] and [`revive`] can be used instead by configuring the [`"go.lintTool"`](settings.md#go.lintTool) setting. For a complete overview of linter options, see the [documentation for diagnostic tools](tools.md#diagnostics).
### Analyze vulnerabilities in dependencies
The extension checks the 3rd party dependencies in your code and surfaces vulnerabilities known to the [Go vulnerability database](https://vuln.go.dev). There are two modes that complement each other.
* Import-based analysis: this can be enabled using the [`"go.diagnostic.vulncheck": "Imports"`](settings.md#go.diagnostic.vulncheck) setting. You can turn on and off this analysis conveniently with the ["Go: Toggle Vulncheck"](commands.md#go-toggle-vulncheck) command. In this mode, `gopls` reports vulnerabilities that affect packages directly and indirectly used by your code. The diagnostics are reported in the `go.mod` file along with quick fixes to help upgrading vulnerable modules.
* `Govulncheck` analysis: this is based on the [`golang.org/x/vuln/cmd/govulncheck`](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck) tool, which is embedded in `gopls`. This provides a low-noise, reliable way to inspect known vulnerabilities. This only surfaces vulnerabilities that actually affect your code, based on which functions in your code are transitively calling vulnerable functions. This can be accessible by the `gopls` [`run_govulncheck`](settings.md#uicodelenses) code lens. The import-based analysis result also provides the `"Run govulncheck to verify"` option as a quick fix.
These features require _`gopls` v0.11.0 or newer_.
Please share your feedback at https://go.dev/s/vsc-vulncheck-feedback.
Report a bug and feature request in [our issue tracker](https://github.com/golang/vscode-go/issues/new).
**Notes and Caveats**
- The import-based analysis uses the list of packages in the workspace modules, which may be different from what you see from `go.mod` files if `go.work` or module `replace`/`exclude` is used.
- The govulncheck analysis result can become stale as you modify code or the Go vulnerability database is updated. In order to invalidate the analysis results manually, use the [`"Reset go.mod diagnostics"`] codelens shown on the top of the `go.mod` file. Otherwise, the result will be automatically invalidated after an hour.
- These features currently don't report vulnerabilities in the standard libraries or tool chains. We are still investigating UX on where to surface the findings and how to help users handle the issues.
- The extension does not scan private packages nor send any information on private modules. All the analysis is done by pulling a list of known vulnerable modules from the Go vulnerability database and then computing the intersection locally.
## Run and test in the editor
### Run your code
To run your code without debugging, use the keyboard shortcut `Ctrl+F5` or run the command `Debug: Start without Debugging`. To debug, see [Debugging](#debugging) below.
This command requires you to have a [launch configuration](debugging.md#launch-configuration) in a `launch.json` file. To open or create your `launch.json`, run the `Debug: Open launch.json` command. Use the default `Go: Launch file` configuration.
Behind the scenes, the `Debug: Start without Debugging` command calls `go run`. `go run` usually requires the path to the file to run, so your `launch.json` should contain `"program": "${file}"`.
### Test and benchmark
[Test UI](https://code.visualstudio.com/api/extension-guides/testing) and [Code lenses](https://code.visualstudio.com/blogs/2017/02/12/code-lens-roundup) allow users to easily run tests, benchmarks, and profiles for a given function, file, package, or workspace.
Alternatively, the same functionality is available through a set of commands: [`Go: Test Function At Cursor`](commands.md#go-test-function-at-cursor), [`Go: Test File`](commands.md#go-test-file), [`Go: Test Package`](commands.md#go-test-package), and [`Go: Test All Packages in Workspace`](commands.md#go-test-all-packages-in-workspace).
### Code Coverage
Show code coverage in the editor, either after running a test or on-demand. This can be done via the commands: [`Go: Apply Cover Profile`](commands.md#go-apply-cover-profile) and [`Go: Toggle Test Coverage in Current Package`](commands.md#go-toggle-test-coverage-in-current-package).
### Profiling
"Go Test: Profile" menu in [Test UI](https://code.visualstudio.com/api/extension-guides/testing) collects CPU/Memory/Mutex profiles and allows visualizing them using pprof (`go tool pprof`).
## [Debugging](debugging.md)
This extension offers debugging of Go programs. See the [debugging documentation](debugging.md) for more information.
## Other
### Go Playground
Export your current file to the [Go Playground](https://play.golang.org) via the [`Go: Run On Go Playground`](settings.md#go-run-on-go-playground) command. This is useful for quickly creating a piece of sample code.
[`gopls`]: gopls.md
[`staticcheck`]: https://staticcheck.io/
[`golint`]: https://pkg.go.dev/golang.org/x/lint/golint?tab=overview
[`golangci-lint`]: https://golangci-lint.run/
[`revive`]: https://github.com/mgechev/revive
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/gopath.md
# `GOPATH`
The `GOPATH` environment variable is a fundamental part of writing Go code
**without** [Go modules]. It specifies the location of your workspace, and it
defaults to `$HOME/go`. A `GOPATH` directory contains `src`, `bin`, and `pkg`
directories. Your code is typically located in the `$GOPATH/src` directory.
If you are not familiar with Go and `GOPATH`, please first read about [writing
Go code with `GOPATH`](https://golang.org/doc/gopath_code.html#GOPATH).
**If you are just starting out with Go, we recommend [using Go modules](https://go.dev/blog/using-go-modules) instead of GOPATH.**
## Overview
* [Check the value of `GOPATH`](#check-the-value-of-gopath)
* [Setting `GOPATH`](#setting-gopath)
* [Different `GOPATH`s for different projects](#different-gopaths-for-different-projects)
* [Automatically inferring your `GOPATH`](#automatically-inferring-your-gopath)
* [Install tools to a separate `GOBIN`](#install-tools-to-a-separate-gobin)
* [Install tools to a separate `GOPATH`](#install-tools-to-a-separate-gopath)
## Check the value of `GOPATH`
First, it's useful to quickly check that you are using the right `GOPATH`. Two commands report the `GOPATH` value used by the VS Code Go extension: (1) [`Go: Current GOPATH`](commands.md#go-current-gopath), or (2) [`Go: Locate Configured Go Tools`](commands.md#go-locate-configured-go-tools). Use either of these commands to check which `GOPATH` the extension is using.
If the `GOPATH` value is incorrect, see the details below on how to configure it.
## Setting `GOPATH`
If you have chosen not to use [Go modules], you will need to configure your `GOPATH`.
Setting `GOPATH` is typically as simple as setting the environment variable once in your system's configuration. Take a look at the [Setting `GOPATH` Wiki](https://github.com/golang/go/wiki/SettingGOPATH) if you're unsure how to do this.
By default, the extension uses the value of the environment variable `GOPATH`. If no such environment variable is set, the extension runs `go env` and uses the `GOPATH` reported by the `go` command.
Note that, much like a `PATH` variable, `GOPATH` can contain multiple directory paths, separated by `:` or `;`. This allows you to set different `GOPATH`s for different projects.
Still, there are a number of cases in which you might want a more complicated `GOPATH` set-up. Below, we explain more complex ways to configure and manage your `GOPATH` within the VS Code Go extension.
## Different `GOPATH`s for different projects
Setting [`go.gopath`](settings.md#go.gopath) in your [user settings](https://code.visualstudio.com/docs/getstarted/settings) overrides the environment's `GOPATH` value.
[Workspace settings](https://code.visualstudio.com/docs/getstarted/settings#_workspace-settings) override user settings, so you can use the [`go.gopath`](settings.md#go.gopath) setting to set different `GOPATH`s for different projects. A `GOPATH` can also contain multiple directories, so this setting is not necessary to achieve this behavior.
## Automatically inferring your `GOPATH`
**NOTE: This feature only works in `GOPATH` mode, not in module mode.**
The [`go.inferGopath`](settings.md#go.inferGopath) setting overrides the [`go.gopath`](settings.md#go.gopath) setting. If you set [`go.inferGopath`](settings.md#go.inferGopath) to `true`, the extension will try to infer your `GOPATH` based on the workspace opened in VS Code. This is done by searching for a `src` directory in your workspace. The parent of this `src` directory is then added to your [global `GOPATH`](#setting-gopath) (`go env GOPATH`).
For example, say your global `GOPATH` is `$HOME/go`, but you are working in a repository with the following structure.
```bash
foo/
└── bar
└── src
└── main.go
```
If you open the `foo` directory as your workspace root in VS Code, [`"go.inferGopath"`](settings.md#go.inferGopath) will set your `GOPATH` to `$HOME/go:/path/to/foo/bar`.
This setting is useful because it allows you to avoid setting the `GOPATH` in the workspace settings of each of your projects.
## Install tools to a separate `GOBIN`
If you switch frequently between `GOPATH`s, you may find that the extension prompts you to install tools for every `GOPATH`. You can resolve this by making sure your tool installations are on your `PATH`, or you can configure a separate directory for tool installation: `GOBIN`. This environment variable tells the `go` command where to install all binaries. Configure it by setting:
```json5
"go.toolsEnvVars": {
"GOBIN": "path/to/gobin"
}
```
## Install tools to a separate `GOPATH`
**NOTE: The following is only relevant if you are using a Go version that does not support [Go modules], that is, any version of Go before 1.11.**
Before Go 1.11, the `go get` command installed tools and their source code to your `GOPATH`. Because this extension uses a lot of different tools, this causes clutter in your `GOPATH`. If you wish to reduce this clutter, you can have the extension install tools to a different location. This also addresses the issue described above, when switching `GOPATHs` forces you to reinstall Go tools.
This can be done by setting [`"go.toolsGopath"`](settings.md#go.toolsGopath) to an alternate path, only for tool installations. After you configure this setting, be sure to run the [`Go: Install/Update Tools`](commands.md#go-installupdate-tools) command so that the Go tools get installed to the provided location.
The extension will fall back to your existing `GOPATH` if tools are not found in the [`go.toolsGopath`](settings.md#go.toolsGopath) directory.
[Go modules]: https://go.dev/blog/using-go-modules
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/settings.md
# Settings
This extension is highly configurable, and as such, offers a number of settings. These can be configured by modifying your [User or Workspace Settings](https://code.visualstudio.com/docs/getstarted/settings).
To navigate to your settings, open the Command Palette (Ctrl+Shift+P or Cmd+Shift+P) and search for "settings". The simplest way to modify your settings is through "Preferences: Open Settings (UI)".
For tuning the features provided by `gopls`, see the [section](settings.md#settings-for-gopls) for `gopls` settings.
## Latest changes
The settings described below are up-to-date as of January 2021. We do our best to keep documentation current, but if a setting is missing, you can always consult the full list in the Extensions view. Documentation for each setting should also be visible in the Settings UI.
To view the list of settings:
1. Navigate to the Extensions view (Ctrl+Shift+X).
2. Find the Go extension and click on it to open the Extension Editor.
3. Click on the `Feature Contributions` tab.
4. Scroll through the list under `Settings`.
## Security
This extension runs a few [third-party command-line tools](tools.md) found from the locations determined by the `PATH` or `Path` environment variable, and the settings such as `"go.alternateTools"` or `"go.toolsGopath"`. Configuring them in workspace settings allows users to conveniently select a different set of tools based on project's need, but also allows attackers to run arbitrary binaries on your machine if they successfully convince you to open a random repository. In order to reduce the security risk, the extension reads those settings from user settings by default. If the repository can be trusted and workspace settings must be used, you can mark the workspace as a trusted workspace using the `"Go: Toggle Workspace Trust Flag"` command.
## Detailed list
### `go.addTags`
Tags and options configured here will be used by the Add Tags command to add tags to struct fields. If promptForTags is true, then user will be prompted for tags and options. By default, json tags are added.
| Properties | Description |
| --- | --- |
| `options` | Comma separated tag=options pairs to be used by Go: Add Tags command
Default: `"json=omitempty"` |
| `promptForTags` | If true, Go: Add Tags command will prompt the user to provide tags, options, transform values instead of using the configured values
Default: `false` |
| `tags` | Comma separated tags to be used by Go: Add Tags command
Default: `"json"` |
| `template` | Custom format used by Go: Add Tags command for the tag value to be applied
Default: `""` |
| `transform` | Transformation rule used by Go: Add Tags command to add tags
Allowed Options: `snakecase`, `camelcase`, `lispcase`, `pascalcase`, `keep`
Default: `"snakecase"` |
Default:
```
{
"options" : "json=omitempty",
"promptForTags" : false,
"tags" : "json",
"template" : "",
"transform" : "snakecase",
}
```
### `go.alternateTools`
Alternate tools or alternate paths for the same tools used by the Go extension. Provide either absolute path or the name of the binary in GOPATH/bin, GOROOT/bin or PATH. Useful when you want to use wrapper script for the Go tools.
| Properties | Description |
| --- | --- |
| `customFormatter` | Custom formatter to use instead of the language server. This should be used with the `custom` option in `#go.formatTool#`.
Default: `""` |
| `dlv` | Alternate tool to use instead of the dlv binary or alternate path to use for the dlv binary.
Default: `"dlv"` |
| `go` | Alternate tool to use instead of the go binary or alternate path to use for the go binary.
Default: `"go"` |
| `gopls` | Alternate tool to use instead of the gopls binary or alternate path to use for the gopls binary.
Default: `"gopls"` |
### `go.buildFlags`
Flags to `go build`/`go test` used during build-on-save or running tests. (e.g. ["-ldflags='-s'"]) This is propagated to the language server if `gopls.build.buildFlags` is not specified.
### `go.buildOnSave (deprecated)`
Enable the Go language server (`#go.useLanguageServer#`) to diagnose compile errors.
Compiles code on file save using 'go build' or 'go test -c'. Not applicable when using the language server.
Allowed Options: `package`, `workspace`, `off`
Default: `"package"`
### `go.buildTags`
The Go build tags to use for all commands, that support a `-tags '...'` argument. When running tests, go.testTags will be used instead if it was set. This is propagated to the language server if `gopls.build.buildFlags` is not specified.
Default: `""`
### `go.coverMode`
When generating code coverage, the value for -covermode. 'default' is the default value chosen by the 'go test' command.
Allowed Options: `default`, `set`, `count`, `atomic`
Default: `"default"`
### `go.coverOnSave`
If true, runs 'go test -coverprofile' on save and shows test coverage.
Default: `false`
### `go.coverOnSingleTest`
If true, shows test coverage when Go: Test Function at cursor command is run.
Default: `false`
### `go.coverOnSingleTestFile`
If true, shows test coverage when Go: Test Single File command is run.
Default: `false`
### `go.coverOnTestPackage`
If true, shows test coverage when Go: Test Package command is run.
Default: `true`
### `go.coverShowCounts`
When generating code coverage, should counts be shown as --374--
Default: `false`
### `go.coverageDecorator`
This option lets you choose the way to display code coverage. Choose either to highlight the complete line or to show a decorator in the gutter. You can customize the colors and borders for the former and the style for the latter.
| Properties | Description |
| --- | --- |
| `coveredBorderColor` | Color to use for the border of covered code. |
| `coveredGutterStyle` | Gutter style to indicate covered code.
Allowed Options: `blockblue`, `blockred`, `blockgreen`, `blockyellow`, `slashred`, `slashgreen`, `slashblue`, `slashyellow`, `verticalred`, `verticalgreen`, `verticalblue`, `verticalyellow` |
| `coveredHighlightColor` | Color in the rgba format to use to highlight covered code. |
| `type` |
Allowed Options: `highlight`, `gutter` |
| `uncoveredBorderColor` | Color to use for the border of uncovered code. |
| `uncoveredGutterStyle` | Gutter style to indicate covered code.
Allowed Options: `blockblue`, `blockred`, `blockgreen`, `blockyellow`, `slashred`, `slashgreen`, `slashblue`, `slashyellow`, `verticalred`, `verticalgreen`, `verticalblue`, `verticalyellow` |
| `uncoveredHighlightColor` | Color in the rgba format to use to highlight uncovered code. |
Default:
```
{
"coveredBorderColor" : "rgba(64,128,128,0.5)",
"coveredGutterStyle" : "blockblue",
"coveredHighlightColor" : "rgba(64,128,128,0.5)",
"type" : "highlight",
"uncoveredBorderColor" : "rgba(128,64,64,0.25)",
"uncoveredGutterStyle" : "slashyellow",
"uncoveredHighlightColor" : "rgba(128,64,64,0.25)",
}
```
### `go.coverageOptions`
Use these options to control whether only covered or only uncovered code or both should be highlighted after running test coverage
Allowed Options: `showCoveredCodeOnly`, `showUncoveredCodeOnly`, `showBothCoveredAndUncoveredCode`
Default: `"showBothCoveredAndUncoveredCode"`
### `go.delveConfig`
Delve settings that applies to all debugging sessions. Debug configuration in the launch.json file will override these values.
| Properties | Description |
| --- | --- |
| `apiVersion` | Delve Api Version to use. Default value is 2. This applies only when using the 'legacy' debug adapter.
Allowed Options: `1`, `2`
Default: `2` |
| `debugAdapter` | Select which debug adapter to use by default. This is also used for choosing which debug adapter to use when no launch.json is present and with codelenses.
Allowed Options: `legacy`, `dlv-dap`
Default: `"dlv-dap"` |
| `dlvFlags` | Extra flags for `dlv`. See `dlv help` for the full list of supported. Flags such as `--log-output`, `--log`, `--log-dest`, `--api-version`, `--output`, `--backend` already have corresponding properties in the debug configuration, and flags such as `--listen` and `--headless` are used internally. If they are specified in `dlvFlags`, they may be ignored or cause an error. |
| `dlvLoadConfig` | LoadConfig describes to delve, how to load values from target's memory. Ignored by 'dlv-dap'.
Default: ``` { "followPointers" : true,
"maxArrayValues" : 64,
"maxStringLen" : 64,
"maxStructFields" : -1,
"maxVariableRecurse" : 1,
} ``` |
| `hideSystemGoroutines` | Boolean value to indicate whether system goroutines should be hidden from call stack view.
Default: `false` |
| `logOutput` | Comma separated list of components that should produce debug output. Maps to dlv's `--log-output` flag. Check `dlv log` for details.
Allowed Options: `debugger`, `gdbwire`, `lldbout`, `debuglineerr`, `rpc`, `dap`
Default: `"debugger"` |
| `showGlobalVariables` | Boolean value to indicate whether global package variables should be shown in the variables pane or not.
Default: `false` |
| `showLog` | Show log output from the delve debugger. Maps to dlv's `--log` flag.
Default: `false` |
| `showRegisters` | Boolean value to indicate whether register variables should be shown in the variables pane or not.
Default: `false` |
| `substitutePath` | An array of mappings from a local path to the remote path that is used by the debuggee. The debug adapter will replace the local path with the remote path in all of the calls. Overridden by `remotePath` (in attach request). |
### `go.diagnostic.vulncheck`
(Experimental) vulncheck enables vulnerability scanning.
Allowed Options:
* `Imports`: `"Imports"`: In Imports mode, `gopls` will report vulnerabilities that affect packages
directly and indirectly used by the analyzed main module.
* `Off`: `"Off"`: Disable vulnerability analysis.
* `Prompt`: `"Prompt"`: Vulncheck can be triggered via prompt.
Default: `"Prompt"`
### `go.disableConcurrentTests`
If true, tests will not run concurrently. When a new test run is started, the previous will be cancelled.
Default: `false`
### `go.editorContextMenuCommands`
Experimental Feature: Enable/Disable entries from the context menu in the editor.
| Properties | Description |
| --- | --- |
| `addImport` | If true, adds command to import a package to the editor context menu
Default: `true` |
| `addTags` | If true, adds command to add configured tags from struct fields to the editor context menu
Default: `true` |
| `benchmarkAtCursor` | If true, adds command to benchmark the test under the cursor to the editor context menu
Default: `false` |
| `compilerDetails` | If true, adds command to show compiler optimization details under the cursor to the editor context menu
Default: `false` |
| `debugTestAtCursor` | If true, adds command to debug the test under the cursor to the editor context menu
Default: `false` |
| `fillStruct` | If true, adds command to fill struct literal with default values to the editor context menu
Default: `true` |
| `generateTestForFile` | If true, adds command to generate unit tests for current file to the editor context menu
Default: `true` |
| `generateTestForFunction` | If true, adds command to generate unit tests for function under the cursor to the editor context menu
Default: `true` |
| `generateTestForPackage` | If true, adds command to generate unit tests for current package to the editor context menu
Default: `true` |
| `playground` | If true, adds command to upload the current file or selection to the Go Playground
Default: `true` |
| `removeTags` | If true, adds command to remove configured tags from struct fields to the editor context menu
Default: `true` |
| `testAtCursor` | If true, adds command to run the test under the cursor to the editor context menu
Default: `false` |
| `testCoverage` | If true, adds command to run test coverage to the editor context menu
Default: `true` |
| `testFile` | If true, adds command to run all tests in the current file to the editor context menu
Default: `true` |
| `testPackage` | If true, adds command to run all tests in the current package to the editor context menu
Default: `true` |
| `toggleTestFile` | If true, adds command to toggle between a Go file and its test file to the editor context menu
Default: `true` |
Default:
```
{
"addImport" : true,
"addTags" : true,
"benchmarkAtCursor" : false,
"compilerDetails" : false,
"debugTestAtCursor" : true,
"fillStruct" : false,
"generateTestForFile" : false,
"generateTestForFunction" : true,
"generateTestForPackage" : false,
"playground" : true,
"removeTags" : false,
"testAtCursor" : true,
"testCoverage" : true,
"testFile" : false,
"testPackage" : false,
"toggleTestFile" : true,
}
```
### `go.enableCodeLens`
Feature level setting to enable/disable code lens for references and run/debug tests
| Properties | Description |
| --- | --- |
| `runtest` | If true, enables code lens for running and debugging tests
Default: `true` |
Default:
```
{
"runtest" : true,
}
```
### `go.experiments`
Disable experimental features. These features are only available in the pre-release version.
| Properties | Description |
| --- | --- |
| `testExplorer` | Prefer the experimental test explorer
Default: `true` |
Default:
```
{
"testExplorer" : true,
}
```
### `go.formatFlags`
Flags to pass to format tool (e.g. ["-s"]). Not applicable when using the language server.
### `go.formatTool`
Specifies the tool for formatting Go code. The default is `default`, which uses the language server `gopls` as formatting provider. To configure gopls's formatting, see the 'gopls.formatting' settings. When a specific tool (e.g., `gofmt`, `goimports`) is selected, the extension will run it instead.
Allowed Options:
* `default`: Formatting is performed by the language server, gopls. (recommended)
* `gofmt`: Formats using `gofmt`, the standard Go formatter. See https://pkg.go.dev/cmd/gofmt.
* `goimports`: Formats using `goimports`, which organizes imports and applies `gofmt`. See https://pkg.go.dev/golang.org/x/tools/cmd/goimports.
* `goformat`: Formats using `goformat`, a configurable version of `gofmt`. See https://github.com/mbenkmann/goformat. (Deprecated due to lack of generics support)
* `gofumpt`: Formats using `gofumpt`, a stricter version of `gofmt`. See https://github.com/mvdan/gofumpt. Note: `gopls` can also be configured to use `gofumpt` via the `#gopls.formatting.gofumpt#` setting.
* `custom`: Formats using a custom tool. The tool's path must be specified in the `#go.alternateTools#` setting under the `customFormatter` key.
Default: `"default"`
### `go.generateTestsFlags`
Additional command line flags to pass to `gotests` for generating tests.
### `go.gopath`
Specify GOPATH here to override the one that is set as environment variable. The inferred GOPATH from workspace root overrides this, if go.inferGopath is set to true.
### `go.goroot`
Specifies the GOROOT to use when no environment variable is set.
### `go.inferGopath`
Infer GOPATH from the workspace root. This is ignored when using Go Modules.
Default: `false`
### `go.inlayHints.assignVariableTypes`
`"assignVariableTypes"` controls inlay hints for variable types in assign statements:
```go
i/* int*/, j/* int*/ := 0, len(r)-1
```
Default: `false`
### `go.inlayHints.compositeLiteralFields`
`"compositeLiteralFields"` inlay hints for composite literal field names:
```go
{/*in: */"Hello, world", /*want: */"dlrow ,olleH"}
```
Default: `false`
### `go.inlayHints.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"},
}
```
Default: `false`
### `go.inlayHints.constantValues`
`"constantValues"` controls inlay hints for constant values:
```go
const (
KindNone Kind = iota/* = 0*/
KindPrint/* = 1*/
KindPrintf/* = 2*/
KindErrorf/* = 3*/
)
```
Default: `false`
### `go.inlayHints.functionTypeParameters`
`"functionTypeParameters"` inlay hints for implicit type parameters on generic functions:
```go
myFoo/*[int, string]*/(1, "hello")
```
Default: `false`
### `go.inlayHints.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.
Default: `false`
### `go.inlayHints.parameterNames`
`"parameterNames"` controls inlay hints for parameter names:
```go
parseInt(/* str: */ "123", /* radix: */ 8)
```
Default: `false`
### `go.inlayHints.rangeVariableTypes`
`"rangeVariableTypes"` controls inlay hints for variable types in range statements:
```go
for k/* int*/, v/* string*/ := range []string{} {
fmt.Println(k, v)
}
```
Default: `false`
### `go.installDependenciesWhenBuilding`
If true, then `-i` flag will be passed to `go build` everytime the code is compiled. Since Go 1.10, setting this may be unnecessary unless you are in GOPATH mode and do not use the language server.
Default: `false`
### `go.languageServerFlags`
Flags like -rpc.trace and -logfile to be used while running the language server.
### `go.lintFlags`
Flags to pass to Lint tool (e.g. ["-min_confidence=.8"])
### `go.lintOnSave`
Lints code on file save using the configured Lint tool. Options are 'file', 'package', 'workspace' or 'off'.
Allowed Options:
* `file`: lint the current file on file saving
* `package`: lint the current package on file saving
* `workspace`: lint all the packages in the current workspace root folder on file saving
* `off`: do not run lint automatically
Default: `"package"`
### `go.lintTool`
Specifies an additional client-side linting tool that should be run by the Go extension. By default (unset), no additional linter is run. This feature is additional to diagnostics reported by the language server, gopls. Since Gopls incorporates the entire staticcheck analyzer suite, it is typically unnecessary to run the staticcheck tool as well. To configure gopls's linting, see the 'gopls.ui.diagnostic' settings.
Allowed Options:
* `staticcheck`: Run `staticcheck`.
* `golint`: Run `golint`.
* `golangci-lint`: Run `golangci-lint` v1.
* `golangci-lint-v2`: Run `golangci-lint` v2.
* `revive`: Run `revive`.
### `go.logging.level (deprecated)`
This setting is deprecated. Use 'Developer: Set Log Level...' command to control logging level instead.
### `go.playground`
The flags configured here will be passed through to command `goplay`
| Properties | Description |
| --- | --- |
| `openbrowser` | Whether to open the created Go Playground in the default browser
Default: `true` |
| `run` | Whether to run the created Go Playground after creation
Default: `true` |
| `share` | Whether to make the created Go Playground shareable
Default: `true` |
Default:
```
{
"openbrowser" : true,
"run" : true,
"share" : true,
}
```
### `go.removeTags`
Tags and options configured here will be used by the Remove Tags command to remove tags to struct fields. If promptForTags is true, then user will be prompted for tags and options. By default, all tags and options will be removed.
| Properties | Description |
| --- | --- |
| `options` | Comma separated tag=options pairs to be used by Go: Remove Tags command
Default: `"json=omitempty"` |
| `promptForTags` | If true, Go: Remove Tags command will prompt the user to provide tags and options instead of using the configured values
Default: `false` |
| `tags` | Comma separated tags to be used by Go: Remove Tags command
Default: `"json"` |
Default:
```
{
"options" : "",
"promptForTags" : false,
"tags" : "",
}
```
### `go.showWelcome`
Specifies whether to show the Welcome experience on first install
Default: `true`
### `go.survey.prompt`
Prompt for surveys, including the gopls survey and the Go developer survey.
Default: `true`
### `go.tasks.provideDefault`
enable the default go build/test task provider.
Default: `true`
### `go.terminal.activateEnvironment`
Apply the Go & PATH environment variables used by the extension to all integrated terminals.
Default: `true`
### `go.testEnvFile`
Absolute path to a file containing environment variables definitions. File contents should be of the form key=value.
### `go.testEnvVars`
Environment variables that will be passed to the process that runs the Go tests
### `go.testExplorer.alwaysRunBenchmarks`
Run benchmarks when running all tests in a file or folder.
Default: `false`
### `go.testExplorer.concatenateMessages`
Concatenate all test log messages for a given location into a single message.
Default: `true`
### `go.testExplorer.enable`
Enable the Go test explorer
Default: `true`
### `go.testExplorer.packageDisplayMode`
Present packages in the test explorer flat or nested.
Allowed Options: `flat`, `nested`
Default: `"flat"`
### `go.testExplorer.showDynamicSubtestsInEditor`
Set the source location of dynamically discovered subtests to the location of the containing function. As a result, dynamically discovered subtests will be added to the gutter test widget of the containing function.
Default: `false`
### `go.testExplorer.showOutput`
Open the test output terminal when a test run is started.
Default: `true`
### `go.testFlags`
Flags to pass to `go test`. If null, then buildFlags will be used. This is not propagated to the language server.
### `go.testOnSave`
Run 'go test' on save for current package. It is not advised to set this to `true` when you have Auto Save enabled.
Default: `false`
### `go.testTags`
The Go build tags to use for when running tests. If null, then buildTags will be used.
### `go.testTimeout`
Specifies the timeout for go test in ParseDuration format.
Default: `"30s"`
### `go.toolsEnvVars`
Environment variables that will be passed to the tools that run the Go tools (e.g. CGO_CFLAGS) and debuggee process launched by Delve. Format as string key:value pairs. When debugging, merged with `envFile` and `env` values with precedence `env` > `envFile` > `go.toolsEnvVars`.
### `go.toolsGopath`
Location to install the Go tools that the extension depends on if you don't want them in your GOPATH.
### `go.toolsManagement.autoUpdate`
Automatically update the tools used by the extension, without prompting the user.
Default: `false`
### `go.toolsManagement.checkForUpdates`
Specify whether to prompt about new versions of Go and the Go tools (currently, only `gopls`) the extension depends on
Allowed Options:
* `proxy`: keeps notified of new releases by checking the Go module proxy (GOPROXY)
* `local`: checks only the minimum tools versions required by the extension
* `off`: completely disables version check (not recommended)
Default: `"proxy"`
### `go.toolsManagement.go`
The path to the `go` binary used to install the Go tools. If it's empty, the same `go` binary chosen for the project will be used for tool installation.
Default: `""`
### `go.trace.server`
Trace the communication between VS Code and the Go language server.
Allowed Options: `off`, `messages`, `verbose`
Default: `"off"`
### `go.useLanguageServer`
Enable intellisense, code navigation, refactoring, formatting & diagnostics for Go. The features are powered by the Go language server "gopls".
Default: `true`
### `go.vetFlags`
Flags to pass to `go tool vet` (e.g. ["-all", "-shadow"]). Not applicable when using the language server's diagnostics.
### `go.vetOnSave`
Vets code on file save using 'go tool vet'. Not applicable when using the language server's diagnostics.
Allowed Options:
* `package`: vet the current package on file saving
* `workspace`: vet all the packages in the current workspace root folder on file saving
* `off`: do not run vet automatically
Default: `"package"`
### `gopls`
Customize `gopls` behavior by specifying the gopls' settings in this section. For example,
```
"gopls" : {
"build.directoryFilters": ["-node_modules"]
...
}
```
This section is directly read by `gopls`. See the [`gopls` section](#settings-for-gopls) section for the full list of `gopls` settings.
## Settings for `gopls`
Configure the default Go language server ('gopls'). In most cases, configuring this section is unnecessary. See [the documentation](https://github.com/golang/tools/blob/master/gopls/doc/settings.md) for all available settings.
### `build.buildFlags`
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`.
If unspecified, values of `go.buildFlags, go.buildTags` will be propagated.
### `build.directoryFilters`
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"]`
### `build.env`
env adds environment variables to external commands run by `gopls`, most notably `go list`.
### `build.expandWorkspaceToModule`
(Experimental) 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`
### `build.memoryMode`
(Experimental) obsolete, no effect
Default: `""`
### `build.standaloneTags`
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"]`
### `build.templateExtensions`
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.)
### `build.workspaceFiles`
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.
### `formatting.gofumpt`
gofumpt indicates if we should run gofumpt formatting.
Default: `false`
### `formatting.local`
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: `""`
### `ui.codelenses`
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.
}
...
}
```
| Properties | Description |
| --- | --- |
| `generate` | `"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: `true` |
| `regenerate_cgo` | `"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: `true` |
| `run_govulncheck` | `"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: `true` |
| `test` | `"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: `false` |
| `tidy` | `"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: `true` |
| `upgrade_dependency` | `"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: `true` |
| `vendor` | `"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: `true` |
| `vulncheck` | (Experimental) `"vulncheck"`: Run govulncheck
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: `false` |
### `ui.completion.completeFunctionCalls`
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`
### `ui.completion.completionBudget`
(For Debugging) 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"`
### `ui.completion.experimentalPostfixCompletions`
(Experimental) experimentalPostfixCompletions enables artificial method snippets
such as "someSlice.sort!".
Default: `true`
### `ui.completion.matcher`
(Advanced) matcher sets the algorithm that is used when calculating completion
candidates.
Allowed Options: `CaseInsensitive`, `CaseSensitive`, `Fuzzy`
Default: `"Fuzzy"`
### `ui.completion.usePlaceholders`
placeholders enables placeholders for function parameters or struct
fields in completion responses.
Default: `false`
### `ui.diagnostic.analyses`
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.
}
...
```
| Properties | Description |
| --- | --- |
| `QF1001` | Apply De Morgan's law
Available since 2021.1
Default: `false` |
| `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: `true` |
| `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: `true` |
| `QF1004` | Use strings.ReplaceAll instead of strings.Replace with n == -1
Available since 2021.1
Default: `true` |
| `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: `false` |
| `QF1006` | Lift if+break into loop condition
Before:
for { if done { break } ... }
After:
for !done { ... }
Available since 2021.1
Default: `false` |
| `QF1007` | Merge conditional assignment into variable declaration
Before:
x := false if someCondition { x = true }
After:
x := someCondition
Available since 2021.1
Default: `false` |
| `QF1008` | Omit embedded fields from selector expression
Available since 2021.1
Default: `false` |
| `QF1009` | Use time.Time.Equal instead of == operator
Available since 2021.1
Default: `true` |
| `QF1010` | Convert slice of bytes to string when printing it
Available since 2021.1
Default: `true` |
| `QF1011` | Omit redundant type from variable declaration
Available since 2021.1
Default: `false` |
| `QF1012` | Use fmt.Fprintf(x, ...) instead of x.Write(fmt.Sprintf(...))
Available since 2022.1
Default: `true` |
| `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: `true` |
| `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: `true` |
| `S1002` | Omit comparison with boolean constant
Before:
if x == true {}
After:
if x {}
Available since 2017.1
Default: `false` |
| `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: `true` |
| `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: `true` |
| `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: `false` |
| `S1006` | Use 'for { ... }' for infinite loops
For infinite loops, using for { ... } is the most idiomatic choice.
Available since 2017.1
Default: `false` |
| `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: `true` |
| `S1008` | Simplify returning boolean expression
Before:
if { return true } return false
After:
return
Available since 2017.1
Default: `false` |
| `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: `true` |
| `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: `true` |
| `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: `false` |
| `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: `true` |
| `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: `false` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `S1021` | Merge variable declaration and assignment
Before:
var x uint x = 1
After:
var x uint = 1
Available since 2017.1
Default: `false` |
| `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: `true` |
| `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: `true` |
| `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: `false` |
| `S1028` | Simplify error construction with fmt.Errorf
Before:
errors.New(fmt.Sprintf(...))
After:
fmt.Errorf(...)
Available since 2017.1
Default: `true` |
| `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: `false` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `S1033` | Unnecessary guard around call to 'delete'
Calling delete on a nil map is a no-op.
Available since 2019.2
Default: `true` |
| `S1034` | Use result of type assertion to simplify cases
Available since 2019.2
Default: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `SA1000` | Invalid regular expression
Available since 2017.1
Default: `false` |
| `SA1001` | Invalid template
Available since 2017.1
Default: `true` |
| `SA1002` | Invalid format in time.Parse
Available since 2017.1
Default: `false` |
| `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: `false` |
| `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: `true` |
| `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: `true` |
| `SA1007` | Invalid URL in net/url.Parse
Available since 2017.1
Default: `false` |
| `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: `true` |
| `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: `false` |
| `SA1011` | Various methods in the 'strings' package expect valid UTF-8, but invalid input is provided
Available since 2017.1
Default: `false` |
| `SA1012` | A nil context.Context is being passed to a function, consider using context.TODO instead
Available since 2017.1
Default: `true` |
| `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: `true` |
| `SA1014` | Non-pointer value passed to Unmarshal or Decode
Available since 2017.1
Default: `false` |
| `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: `false` |
| `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: `true` |
| `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: `false` |
| `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: `false` |
| `SA1020` | Using an invalid host:port pair with a net.Listen-related function
Available since 2017.1
Default: `false` |
| `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: `false` |
| `SA1023` | Modifying the buffer in an io.Writer implementation
Write must not modify the slice data, even temporarily.
Available since 2017.1
Default: `false` |
| `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: `false` |
| `SA1025` | It is not possible to use (*time.Timer).Reset's return value correctly
Available since 2019.1
Default: `false` |
| `SA1026` | Cannot marshal channels or functions
Available since 2019.2
Default: `false` |
| `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: `false` |
| `SA1028` | sort.Slice can only be used on slices
The first argument of sort.Slice must be a slice.
Available since 2020.1
Default: `false` |
| `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: `false` |
| `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: `false` |
| `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: `false` |
| `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: `false` |
| `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: `true` |
| `SA2002` | Called testing.T.FailNow or SkipNow in a goroutine, which isn't allowed
Available since 2017.1
Default: `false` |
| `SA2003` | Deferred Lock right after locking, likely meant to defer Unlock instead
Available since 2017.1
Default: `false` |
| `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: `true` |
| `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: `true` |
| `SA4000` | Binary operator has identical expressions on both sides
Available since 2017.1
Default: `true` |
| `SA4001` | &*x gets simplified to x, it does not copy x
Available since 2017.1
Default: `true` |
| `SA4003` | Comparing unsigned values against negative values is pointless
Available since 2017.1
Default: `true` |
| `SA4004` | The loop exits unconditionally after one iteration
Available since 2017.1
Default: `true` |
| `SA4005` | Field assignment that will never be observed. Did you mean to use a pointer receiver?
Available since 2021.1
Default: `false` |
| `SA4006` | A value assigned to a variable is never read before being overwritten. Forgotten error check or dead code?
Available since 2017.1
Default: `false` |
| `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: `false` |
| `SA4009` | A function argument is overwritten before its first use
Available since 2017.1
Default: `false` |
| `SA4010` | The result of append will never be observed anywhere
Available since 2017.1
Default: `false` |
| `SA4011` | Break statement with no effect. Did you mean to break out of an outer loop?
Available since 2017.1
Default: `true` |
| `SA4012` | Comparing a value against NaN even though no value is equal to NaN
Available since 2017.1
Default: `false` |
| `SA4013` | Negating a boolean twice (!!b) is the same as writing b. This is either redundant, or a typo.
Available since 2017.1
Default: `true` |
| `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: `true` |
| `SA4015` | Calling functions like math.Ceil on floats converted from integers doesn't do anything useful
Available since 2017.1
Default: `false` |
| `SA4016` | Certain bitwise operations, such as x ^ 0, do not do anything useful
Available since 2017.1
Default: `true` |
| `SA4017` | Discarding the return values of a function without side effects, making the call pointless
Available since 2017.1
Default: `false` |
| `SA4018` | Self-assignment of variables
Available since 2017.1
Default: `false` |
| `SA4019` | Multiple, identical build constraints in the same file
Available since 2017.1
Default: `true` |
| `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
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: `true` |
| `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: `true` |
| `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.
This text has been copied from https://golang.org/doc/faq#nil_error, licensed under the Creative Commons Attribution 3.0 License.
Available since 2020.2
Default: `false` |
| `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 and https://golang.org/pkg/builtin/#cap.
Example:
if len(slice) < 0 { fmt.Println("unreachable code") }
Available since 2021.1
Default: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `SA4028` | x % 1 is always zero
Available since 2022.1
Default: `true` |
| `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: `true` |
| `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: `true` |
| `SA4031` | Checking never-nil value against nil
Available since 2022.1
Default: `false` |
| `SA4032` | Comparing runtime.GOOS or runtime.GOARCH against impossible value
Available since 2024.1
Default: `true` |
| `SA5000` | Assignment to nil map
Available since 2017.1
Default: `false` |
| `SA5001` | Deferring Close before checking for a possible error
Available since 2017.1
Default: `true` |
| `SA5002` | The empty for loop ('for {}') spins and can block the scheduler
Available since 2017.1
Default: `false` |
| `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: `true` |
| `SA5004` | 'for { select { ...' with an empty default branch spins
Available since 2017.1
Default: `true` |
| `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: `false` |
| `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: `false` |
| `SA5008` | Invalid struct tag
Available since 2019.2
Default: `true` |
| `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: `false` |
| `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: `false` |
| `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: `false` |
| `SA6000` | Using regexp.Match or related in a loop, should use regexp.Compile
Available since 2017.1
Default: `false` |
| `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: `false` |
| `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 that discuss this problem.
Available since 2017.1
Default: `false` |
| `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: `false` |
| `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/
Available since 2019.2
Default: `true` |
| `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: `true` |
| `SA9001` | Defers in range loops may not run when you expect them to
Available since 2017.1
Default: `false` |
| `SA9002` | Using a non-octal os.FileMode that looks like it was meant to be in octal.
Available since 2017.1
Default: `true` |
| `SA9003` | Empty body in an if or else branch
Available since 2017.1, non-default
Default: `false` |
| `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
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
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: `true` |
| `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: `false` |
| `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: `true` |
| `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: `false` |
| `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: `false` |
| `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: `true` |
| `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.
Available since 2019.1, non-default
Default: `false` |
| `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: `false` |
| `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#mixed-caps - https://go.dev/wiki/CodeReviewComments#initialisms - https://go.dev/wiki/CodeReviewComments#variable-names
Available since 2019.1, non-default
Options initialisms
Default: `false` |
| `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: `false` |
| `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: `false` |
| `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: `false` |
| `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: `false` |
| `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: `false` |
| `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: `false` |
| `ST1015` | A switch's default case should be the first or last case
Available since 2019.1
Default: `false` |
| `ST1016` | Use consistent method receiver names
Available since 2019.1, non-default
Default: `false` |
| `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: `false` |
| `ST1018` | Avoid zero-width and control characters in string literals
Available since 2019.2
Default: `false` |
| `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) – if you want to allow this pattern in your code base, you're advised to disable this check.
Available since 2020.1
Default: `false` |
| `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 for more information on how to write good documentation.
Available since 2020.1, non-default
Default: `false` |
| `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 for more information on how to write good documentation.
Available since 2020.1, non-default
Default: `false` |
| `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 for more information on how to write good documentation.
Available since 2020.1, non-default
Default: `false` |
| `ST1023` | Redundant type in variable declaration
Available since 2021.1, non-default
Default: `false` |
| `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: `true` |
| `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.
Default: `false` |
| `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: `true` |
| `asmdecl` | report mismatches between assembly files and Go declarations
Default: `true` |
| `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: `true` |
| `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: `true` |
| `atomicalign` | check for non-64-bits-aligned arguments to sync/atomic functions
Default: `true` |
| `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.
Default: `true` |
| `bools` | check for common mistakes involving boolean operators
Default: `true` |
| `buildtag` | check //go:build and // +build directives
Default: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `deprecated` | check for use of deprecated identifiers
The deprecated analyzer looks for deprecated symbols and package imports.
See https://go.dev/wiki/Deprecated to learn about Go's convention for documenting and signaling deprecated identifiers.
Default: `true` |
| `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), 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: `true` |
| `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: `true` |
| `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: `true` |
| `errorsastype` | replace errors.As with errors.AsType[T]
This analyzer suggests fixes to simplify uses of [errors.As] of this form:
var myerr *MyErr
if errors.As(err, &myerr) {
handle(myerr)
}
by using the less error-prone generic [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: `true` |
| `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.
Default: `true` |
| `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: `true` |
| `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: `true` |
| `framepointer` | report assembly that clobbers the frame pointer before saving it
Default: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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 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: `true` |
| `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 [ for _, v := range list {
defer func() {
use(v) // incorrect
}()
}
One fix is to create a new variable for each iteration of the loop:
for _, v := range list {
v := v // new var per iteration
defer func() {
use(v) // ok
}()
}
After Go version 1.22, the previous two for loops are equivalent and both are correct.
The next example uses a go statement and has a similar problem [ for _, v := range elem {
go func() {
use(v) // incorrect, and a data race
}()
}
A fix is the same as before. The checker also reports problems in goroutines started by golang.org/x/sync/errgroup.Group. A hard-to-spot variant of this form is common in parallel tests:
func Test(t *testing.T) {
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
use(test) // incorrect, and a data race
})
}
}
The t.Parallel() call causes the rest of the function to execute concurrent with the loop [ The analyzer reports references only in the last statement, as it is not deep enough to understand the effects of subsequent statements that might render the reference benign. ("Last statement" is defined recursively in compound statements such as if, switch, and select.)
See: https://golang.org/doc/go_faq.html#closures_and_goroutines
Default: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `nilfunc` | check for useless comparisons between functions and nil
A useless comparison is one like f == nil as opposed to f() == nil.
Default: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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) 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: `true` |
| `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: `true` |
| `printf` | check consistency of Printf format strings and arguments
The check applies to calls of the formatting functions such as [fmt.Printf] and [fmt.Sprintf], as well as any detected wrappers of those functions such as [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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `false` |
| `shift` | check for shifts that equal or exceed the width of the integer
Default: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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.
Default: `false` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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.)
Default: `true` |
| `stringscut` | replace strings.Index etc. with strings.Cut
This analyzer replaces certain patterns of use of [strings.Index] and string slicing by [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] 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: `true` |
| `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: `true` |
| `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: `true` |
| `structtag` | check that struct field tags conform to reflect.StructTag.Get
Also report certain struct tags (json, xml) used with unexported fields.
Default: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
| `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 and 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: `true` |
| `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.
This analyzer ignores generated code.
Default: `true` |
| `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: `true` |
| `unusedvariable` | check for unused variables and suggest fixes
Default: `true` |
| `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: `true` |
| `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: `true` |
| `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: `true` |
### `ui.diagnostic.analysisProgressReporting`
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`
### `ui.diagnostic.annotations`
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.
| Properties | Description |
| --- | --- |
| `bounds` | `"bounds"` controls bounds checking diagnostics.
Default: `true` |
| `escape` | `"escape"` controls diagnostics about escape choices.
Default: `true` |
| `inline` | `"inline"` controls diagnostics about inlining choices.
Default: `true` |
| `nil` | `"nil"` controls nil checks.
Default: `true` |
### `ui.diagnostic.diagnosticsDelay`
(Advanced) 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"`
### `ui.diagnostic.diagnosticsTrigger`
(Experimental) diagnosticsTrigger controls when to run diagnostics.
Allowed Options:
* `Edit`: `"Edit"`: Trigger diagnostics on file edit and save. (default)
* `Save`: `"Save"`: Trigger diagnostics only on file save. Events like initial workspace load
or configuration change will still trigger diagnostics.
Default: `"Edit"`
### `ui.diagnostic.staticcheck`
(Experimental) 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`
### `ui.diagnostic.staticcheckProvided`
(Experimental)
Default: `false`
### `ui.documentation.hoverKind`
hoverKind controls the information that appears in the hover text.
SingleLine is intended for use only by authors of editor plugins.
Allowed Options:
* `FullDocumentation`
* `NoDocumentation`
* `SingleLine`
* `Structured`: `"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"`
### `ui.documentation.linkTarget`
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"`
### `ui.documentation.linksInHover`
linksInHover controls the presence of documentation links in hover markdown.
Allowed Options:
* `false`: false: do not show links
* `true`: true: show links to the `linkTarget` domain
* `gopls`: `"gopls"`: show links to gopls' internal documentation viewer
Default: `true`
### `ui.navigation.importShortcut`
importShortcut specifies whether import statements should link to
documentation or go to definitions.
Allowed Options: `Both`, `Definition`, `Link`
Default: `"Both"`
### `ui.navigation.symbolMatcher`
(Advanced) symbolMatcher sets the algorithm that is used when finding workspace symbols.
Allowed Options: `CaseInsensitive`, `CaseSensitive`, `FastFuzzy`, `Fuzzy`
Default: `"FastFuzzy"`
### `ui.navigation.symbolScope`
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.
Allowed Options:
* `all`: `"all"` matches symbols in any loaded package, including
dependencies.
* `workspace`: `"workspace"` matches symbols in workspace packages only.
Default: `"all"`
### `ui.navigation.symbolStyle`
(Advanced) symbolStyle controls how symbols are qualified in symbol responses.
Example Usage:
```json5
"gopls": {
...
"symbolStyle": "Dynamic",
...
}
```
Allowed Options:
* `Dynamic`: `"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`: `"Full"` is fully qualified symbols, i.e.
"path/to/pkg.Foo.Field".
* `Package`: `"Package"` is package qualified symbols i.e.
"pkg.Foo.Field".
Default: `"Dynamic"`
### `ui.newGoFileHeader`
newGoFileHeader enables automatic insertion of the copyright comment
and package declaration in a newly created Go file.
Default: `true`
### `ui.noSemanticNumber (deprecated)`
use SemanticTokenTypes["number"] = false instead. See
golang/vscode-go#3632.
(Experimental) noSemanticNumber turns off the sending of the semantic token 'number'
Deprecated: Use SemanticTokenTypes["number"] = false instead. See
golang/vscode-go#3632.
Default: `false`
### `ui.noSemanticString (deprecated)`
use SemanticTokenTypes["string"] = false instead. See
golang/vscode-go#3632
(Experimental) noSemanticString turns off the sending of the semantic token 'string'
Deprecated: Use SemanticTokenTypes["string"] = false instead. See
golang/vscode-go#3632
Default: `false`
### `ui.renameMovesSubpackages`
(Experimental) renameMovesSubpackages enables Rename operations on packages to
move subdirectories of the target package.
Default: `false`
### `ui.semanticTokenModifiers`
(Experimental) semanticTokenModifiers configures the semantic token modifiers. It allows
disabling modifiers by setting each value to false.
By default, all modifiers are enabled.
### `ui.semanticTokenTypes`
(Experimental) semanticTokenTypes configures the semantic token types. It allows
disabling types by setting each value to false.
By default, all types are enabled.
### `ui.semanticTokens`
(Experimental) semanticTokens controls whether the LSP server will send
semantic tokens to the client.
Default: `false`
### `verboseOutput`
(For Debugging) verboseOutput enables additional debug logging.
Default: `false`
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/smoke-test.md
# Smoke Test
Before releasing a new version of the extension, please run the following smoke test to make sure that all features are working.
## Set up
First, clone [golang.org/x/example](https://github.com/golang/example). At the time of writing (June 2020), this repository has not changed since 2017. If it has changed since, these steps may not be exactly reproducible and should be adjusted.
For now, we smoke test the extension only in [`GOPATH`](gopath.md) mode.
If it does not already exist:
```bash
mkdir $GOPATH/src/github.com/golang
```
Then,
```bash
cd $GOPATH/src/github.com/golang
git clone https://github.com/golang/example
cd example
```
Next, [build and sideload the modified Go extension](contributing.md#sideload) and open the `example/hello` directory. Open `hello.go`.
## Test code navigation
1. Go to definition on `fmt.Println`.
2. Go to definition on `stringutil.Reverse`.
3. Find all references of `fmt.Println`.
4. Find all references of `stringutil.Reverse`.
5. Hover over `fmt.Println`.
6. Hover over `stringutil.Reverse`.
## Test autocompletion
1. Trigger autocompletion (Ctrl+Space) after `fmt.`.
2. Trigger autocompletion (Ctrl+Space) after `stringutil.`.
3. Enter a newline in the `main` function and type `fmt.`.
4. Enter a newline in the `main` function and type `parser.`. Expect suggestions from the unimported standard library `go/parser` package.
5. Enter a newline in the `main` function and type `fmt.`. Select the `fmt.Println` completion and observe the outcome. Toggle the `go.useCodeSnippetsOnFunctionSuggest` setting to ensure that placeholders are provided.
6. Test signature help by manually triggering it (Ctrl+Shift+Space) while completing `fmt.Println`.
7. Test signature help by manually triggering it (Ctrl+Shift+Space) while completing `stringutil.Reverse`.
## Test diagnostics
Enable `go.buildOnSave`, `go.vetOnSave`, and `go.lintOnSave`.
1. Add `var x int` to the `main` function and expect a build diagnostic.
2. Add `fmt.Printf("hi", 1)` and expect a vet diagnostic.
3. Add the following function to the bottom of the file and expect a lint diagnostic.
```go
// Hello is hi.
func Hi() {}
```
You can also try toggling the `"package"` and `"workspace"` configurations for these settings.
## Test formatting and import organization
1. Hit enter 3 times in the `main` function and save. Expect formatting to remove all but one line.
2. Remove the `"fmt"` import. Save and expect it to return.
3. Remove the `"github.com/golang/example/stringutil"` import. Save and expect it to return.
4. Confirm that the `Go: Add Import` command works (add `"archive/tar"`).
## Test renaming
1. Add the following to the `main` function, then rename `x` to `y`.
```go
var x int
fmt.Println(x)
```
2. Rename `stringutil.Reverse`. `reverse.go` and `reverse_test.go` should be dirtied.
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/tasks.md
# Using [VS Code Tasks] with Go
From the [VS Code Tasks] documentation:
> Tasks in VS Code can be configured to run scripts and start processes so that . . . existing tools can be used from within VS Code without having to enter a command line or write new code. Workspace or folder specific tasks are configured from the tasks.json file in the .vscode folder for a workspace.
To begin configuring tasks, run the `Tasks: Configure Task` command from the Command Palette (Ctrl+Shift+P).
This will create a `tasks.json` file in your workspace's `.vscode` folder.
Replace the contents of this file with the following and adjust the tasks as needed.
```json5
{
"version": "2.0.0",
"type": "shell",
"command": "go",
"cwd": "${workspaceFolder}",
"tasks": [
{
"label": "install",
"args": ["install", "-v", "./..."],
"group": "build",
},
{
"label": "run",
"args": ["run", "${file}"],
"group": "build",
},
{
"label": "test",
"args": ["test", "-v", "./..."],
"group": "test",
},
],
}
```
You can run these tasks via the `Tasks: Run Task` command or by using the Ctrl+Shift+B shortcut.
You can also define additional tasks to run other commands, like `go generate`. Here's an example of a task to run only a specific test (`MyTestFunction`, in this case):
```json5
{
"label": "MyTestFunction",
"args": [ "test", "./...", "-test.run", "MyTestFunction"]
}
```
If you want to invoke tools other than `go`, you will have to move the `"command": "go"` setting into the task objects. For example:
```json5
{
"version": "2.0.0",
"cwd": "${workspaceFolder}",
"tasks": [
{
"label": "install",
"command": "go",
"args": ["install", "-v", "./..."],
"group": "build",
"type": "shell",
},
{
"label": "run",
"command": "go",
"args": ["run", "${file}"],
"group": "build",
"type": "shell",
},
{
"label": "test",
"command": "go",
"args": ["test", "-v", "./..."],
"group": "test",
"type": "shell",
},
],
}
```
Learn more by reading the [VS Code Tasks] documentation.
[VS Code Tasks]: https://code.visualstudio.com/docs/editor/tasks
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/tools.md
# Tools
This document describes the tools that power the VS Code Go extension.
Tools will be installed by default when you install the extension. You can also manually install or update all of these tools by running the [`Go: Install/Update Tools`](commands.md#go-installupdate-tools) command. The extension uses pinned versions of command-line tools. See the pinned versions in tools information [here](https://github.com/golang/vscode-go/blob/master/extension/src/goToolsInformation.ts). If any tools are missing, you will see an `Analysis Tools Missing` warning in the bottom-right corner of the editor, which will prompt you to install these tools.
VS Code Go will install the tools to your `$GOPATH/bin` by default.
### [`go`]
This extension requires you to install the Go toolchain, meaning that you have the `go` command on your [`PATH`](https://en.wikipedia.org/wiki/PATH_(variable)). To do this, follow [the Go installation guide](https://golang.org/doc/install).
The extension runs the [`go`] command to debug and test your go program. By default, this extension assumes that Go is already installed in your system and the `go` command can be found from the `PATH` (or `Path` in some Windows) environment variable.
This extension works best with the [latest versions of Go](https://golang.org/doc/devel/release.html#policy) but some of the features may continue to work with older versions of Go. The Go release policy states that the two newer major releases are officially supported.
The extension checks for the availability of the new Go release by periodically checking the [official Go distribution site](https://golang.org/dl) and notifies you of the new version.
### [`gopls`]
[`gopls`] is the official Go [language server](https://langserver.org/) developed by the Go team. It is the default backend for most of this extension's IntelliSense, code navigation, code editing, and diagnostics features. When the extension starts, it spawns a `gopls` instance in server mode for each VS Code project.
`gopls` uses the `go` command to analyze your code. The extension automatically propagates necessary settings such as `"go.buildFlags"`, `"go.buildTags"`, `"go.toolsEnvVars"` and the path to the right `go` command to `gopls`. No extra settings should be necessary, but when you need to adjust `gopls`'s behavior further (e.g., enable more advanced analysis features), please see [all the settings for `gopls`](settings.md#settings-for-gopls).
If you encounter issues with `gopls`, please read the [troubleshooting guide](troubleshooting.md#collect-gopls-information). If you want to run the extension without the language server, you can disable it by setting `"go.useLanguageServer": false`.
`gopls` officially supports the four newer major versions of Go. If you are using a very old version of Go, or you explicitly disable the language server, the extension will automatically fall back to the legacy mode. The legacy mode uses old tools instead of `gopls`. Unfortunately many of them are no longer actively maintained and many features the extension provides will not be available.
You can tell whether the extension is using `gopls`, by checking whether the high voltage icon (⚡) is present in the [Go status bar](./ui.md).
`gopls` is under active development, and updating it is important to get new features. The extension periodically checks the [module proxy](https://golang.org/cmd/go/#hdr-Module_proxy_protocol) to detect a new version has been released. When a newer version is available, a pop-up will appear, prompting you to update. If you would like to opt out of this automated update check, set `"go.toolsManagement.checkForUpdates"` to `false`.
For more information about `gopls`, please visit its [documentation](https://golang.org/s/gopls).
### [`dlv`](https://github.com/go-delve/delve)
This extension uses Delve for its debug/test functionalities. The extension currently ships with a thin Debug Adapter that implements the [Debug Adapter protocol](https://microsoft.github.io/debug-adapter-protocol/) and connects VS Code and `dlv`.
For a comprehensive overview of how to debug your Go programs, please see the [debugging guide](./debugging.md).
### [`vscgo`](https://pkg.go.dev/github.com/golang/vscode-go/vscgo)
This tool provides utilities needed by this extension but do not belong to the language server
or debug adapter server. Examples include dependency tools management, developer survey
configuration, and [Go telemetry collection](https://github.com/golang/vscode-go/issues/3121).
This tool is released with the extension and installed in the extension's directory.
### [`goplay`](https://pkg.go.dev/github.com/haya14busa/goplay?tab=overview)
This tool provides support for the [`Go: Run on Go Playground`](features.md#go-playground) command.
### [`gomodifytags`](https://pkg.go.dev/github.com/fatih/gomodifytags?tab=overview)
This tool provides support for the [`Go: Add Tags to Struct Fields`](features.md#add-or-remove-struct-tags) and [`Go: Remove Tags From Struct Fields`](features.md#add-or-remove-struct-tags) commands when using older versions of gopls. The latest
version of gopls has a gopls.modify_tags command which directly invokes the
gomodifytags library.
### [`impl`](https://github.com/josharian/impl)
This tool provides support for the [`Go: Generate Interface Stubs`](features.md#generate-interface-implementation) command.
### [`gotests`](https://github.com/cweill/gotests/)
This tool provides support for the [`Go: Generate Unit Tests`](features.md#generate-unit-tests) set of commands.
### [`staticcheck`]
This is the default lint tool. See the [full list of checks](https://staticcheck.io/docs/checks) that `staticcheck` provides. Other lint tools can be used by configuring the [`"go.lintTool"`](settings.md#go.lintTool) setting.
Other options include:
* [`golangci-lint`]: This meta-linter combines a number of existing lint tools, including [staticcheck](#staticcheck), into one interface.
* [`revive`]: This tool is an enhancement on top of [`golint`], and it provides additional checks.
* [`golint`]: This used to be the default linter used by this extension before it was officially deprecated.
You can use the [`"go.lintFlags"`](settings.md#go.lintFlags) setting to further configure your linter of choice. Most linters can be configured via special configuration files, but you may still need to pass these command-line flags. The configuration documentation for each supported linter is listed here:
* [`staticcheck`](https://staticcheck.io/docs/#configuration)
* [`golangci-lint`](https://golangci-lint.run/usage/configuration/)
* [`revive`](https://github.com/mgechev/revive#command-line-flags)
#### Examples
Enable all [`golangci-lint`] linters and only show errors in new code:
```json5
"go.lintFlags": ["--enable-all", "--new"]
```
Configure `revive` to exclude `vendor` directories and apply extra configuration with a `config.toml` file:
```json5
"go.lintFlags": [
"-exclude=vendor/...",
"-config=${workspaceFolder}/config.toml"
]
```
[`goimports`]: https://pkg.go.dev/golang.org/x/tools/cmd/goimports?tab=doc
[`gofmt`]: https://golang.org/cmd/gofmt/
[`golint`]: https://pkg.go.dev/golang.org/x/lint/golint?tab=overview
[`staticcheck`]: https://pkg.go.dev/honnef.co/go/tools/staticcheck?tab=overview
[`golangci-lint`]: https://golangci-lint.run/
[`revive`]: https://pkg.go.dev/github.com/mgechev/revive?tab=overview
[`gopls`]: https://golang.org/s/gopls
[`go`]: https://golang.org/cmd/go
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/troubleshooting.md
# Troubleshooting
If you suspect that the Go extension is not working correctly, please follow the troubleshooting steps below.
**NOTE: [Debugging](debugging.md#troubleshooting) has its own troubleshooting documentation.**
## Make sure your project compiles
Verify that your project is in good shape by working with it at the command line. 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`.
## Look for serious errors and diagnostics
Check that there aren't any diagnostics that indicate a problem with your workspace. First, check the bottom-center of the VS Code window for any errors. After that, check the package declaration of the any Go files you're working in, and your `go.mod` file. Problems in the workspace configuration can cause many different symptoms. See the [`gopls` workspace setup instructions](https://github.com/golang/tools/blob/master/gopls/doc/workspace.md) for help.
## Check your extension setup
Check the bottom of the VS Code window for any warnings and notifications. For example, address warnings such as "⚠️ Analysis Tools Missing".
Run the [`Go: Locate Configured Go Tools`](commands.md#go-locate-configured-go-tools) command. The output is split into sections.
In the first indented section, check that at least `go-outline`, `dlv`, and `gopls` are installed -- they're necessary for the extension's basic functionality. The other tools [provide optional features](tools.md) and are less important unless you need those features. You can install tools by running the [`Go: Install/Update Tools`](commands.md#go-installupdate-tools) command.
Then, look at the `Workspace Folder` section(s) for the environment in use. Verify that `GOROOT` is set to a valid Go installation; if not, follow the [getting started guide](../README.md#install-go). If `GOPATH` is unset, or surprising, read more about [setting up your `GOPATH`](gopath.md#setting-gopath). Also, `GOMOD` should usually point to your project's `go.mod` file if you're in module mode. (More complicated workspace setups may have a blank `GOMOD`. See the `gopls` [workspace documentation](https://github.com/golang/tools/blob/master/gopls/doc/workspace.md) for more on valid workspace setups.) To change the workspace environment, use settings such as [`go.gopath`](settings.md#go.gopath) and [`go.toolsEnvVars`](settings.md#go.toolsEnvVars).
Finally, take a look at your settings in the JSON form (`Preferences: Open Settings (JSON)`). This is an easier way to quickly see what non-default configurations you have. Consider [reading about](settings.md) any settings you don't understand, or just commenting them out.
## Update tools
It's possible that you are using an outdated version of a tool, so the bug you are encountering may have already been fixed. You can update all tools at once by running the [`Go: Install/Update Tools`](commands.md#go-installupdate-tools) command.
## Restart `gopls`
Many of the extension's features are provided by [`gopls`](https://golang.org/s/gopls), the official language server for Go. `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. You can restart `gopls` using the `Go: Restart Language Server` command.
## Ask for help
After you've done the basic steps above, it's a good time to ask for help. Gophers Slack has a channel for [#vscode](https://gophers.slack.com/archives/C2B4L99RS) that can help debug further. If you're confident the problem is with `gopls`, you can go 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.
## Collect extension logs
Start off by opening the `View` -> `Output` pane. On the right side, open the drop-down titled "Tasks". Any item that starts with "Go" is related to this extension. Browse through these output channels and make note of any error messages.
You can also look directly in the logs of the Extension Host by selecting `Log (Extension Host)`. These may contain a lot of unrelated information, but they may prove useful. If you are trying to get the logs for a specific operation, like go to definition, clear the logs (Clear Output button on the right side), and perform the operation.
Errors may also be logged to the Developer Tools console. These errors may be more difficult to parse, but you can take a look at them by running the `Developer: Toggle Developer Tools` command from the Command Palette (Ctrl+Shift+P).
## Collect `gopls` information
Enable `gopls` tracing by adding the following to your settings:
```json5
"go.languageServerFlags": [
"-rpc.trace"
]
```
The gopls log can be found by navigating to `View` -> `Output`. There will be a drop-down menu titled `Tasks` in the top-right corner. Select the `gopls (server)` item, which will contain the `gopls` logs.
In special cases, you may want to increase the verbosity further:
```json5
"gopls": {
"verboseOutput": true
}
```
## 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 Go version: `go version`
1. Your `gopls` version: `gopls -v version`
1. Your vscode version: `code -v` (The minimum required VS Code version is in the ["engines"](https://github.com/golang/vscode-go/blob/master/package.json#L89) attribute in the package.json file.)
1. Your Go extension version: `Extensions: Show Installed Extensions`
1. Your Go environment: `go env` in the workspace folder
1. Relevant VS Code settings: run `Preferences: Open Settings (JSON)` and include anything in a `[go]` block, and anything that starts with `go.` or `gopls.`
1. Extension and `gopls` logs as seems appropriate for the bug. (Include from the beginning of the logs if possible.)
Once you've collected that information, [file your issue](https://github.com/golang/vscode-go/issues/new/choose).
---
# Source: https://github.com/golang/vscode-go/blob/master/docs/ui.md
# Extension UI
## Using The Go Status Bar
The Go status bar appears in the lower right of the extension window, next to the Editor Language status bar item. Clicking the Go status bar brings up a menu that provides easy access to see and update important information about your Go project. This includes information about the Go environment, the current Go version, the `gopls` trace, and about the current module.
## Using The Language Status Bar
The Language status bar shows status of dependency tools installation or availability of newly released Go versions.
### Go Environment
The `Go Locate Configured Go Tools` command will display the configured GOPATH, GOROOT, tool locations and the results of `go env` in the output window.
### Managing Your Go Version
You can view the current Go version by looking at the status bar item in the bottom left corner of VS Code. Clicking this button and selecting `Choose Go Environment` will present you with a menu from which you can select any version of Go that exists in your $HOME/sdk directory or on . This command is also available through the command pallette using `Go: Choose Go Environment`.
If you are using go1.21 or newer, you can control your Go version using the `GOTOOLCHAIN` environment variable. See https://go.dev/doc/toolchain for more information. To tell the extension to use a different `GOTOOLCHAIN`, use the `go.toolsEnvVars` setting or the Go explorer view.
```
"go.toolsEnvVars": {
"GOTOOLCHAIN": "go1.21.0+auto"
}
```
You will need to reload the window after updating this setting. We are working on improving the version switch workflow.
Previously, the `go.goroot` and `go.alternateTools` settings controlled the Go version used by VS Code Go. If you have configured these settings, they are no longer needed and should be deleted.
### Installing a New Go Version
After selecting any Go version that has not yet been installed (such as Go 1.14.6 in the screenshot above), the binary will be automatically installed in $HOME/sdk and put to use in your environment.
Once the download completes, VS Code Go will make use of this new Go version.
### Language Server Status
`gopls` is the official Go [language server](https://langserver.org/) developed by the Go team. It was developed in response to the release of Go modules, and it is the recommended approach when working with Go modules in VS Code.
When `gopls` is enabled, :zap: is displayed next to the Go version in the Go status bar and the `gopls` version is displayed in the menu.
Selecting `Open 'gopls' trace` will open the trace of the `gopls` server in the output window. Please include this trace when filing an issue related to the extension and `gopls` is enabled.
### Modules Status
When modules are enabled for the file you have open, you can navigate to the `go.mod` file for the project using the menu. If you do not see the `Open go.mod` item, then the extension does not think the file you have open belongs to a module.
More information about [using Go modules](https://go.dev/blog/using-go-modules ) is available on the Go blog.
## Go Explorer View
The view displays the go environment variables (`go env`) that are applied to the file open in the editor. You can customize the list by "Go: Edit Workspace" command (pencil icon), and update modifiable environment variables through this view.
It displays required [tools](tools.md) and their location/version info, too.