vscode-go Documentation

Go extension for Visual Studio Code

4,246 stars TypeScript TypeScript 1 file · ~32,097 tokens #debugger#golang#visual-studio-code#vscode#vscode-extension
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy vscode-go on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name vscode-go --restart always golang/vscode-go:latest

1. Project Overview & Quickstart (golang/vscode-go)

File: README.md

Go for Visual Studio Code

The VS Code Go extension
provides rich language support for the
Go programming language.

Requirements

  • Visual Studio Code 1.90 or newer (or editors compatible with VS Code 1.90+ APIs)
  • Go 1.21 or newer.

Quick Start

Welcome! 👋🏻
Whether you are new to Go or an experienced Go developer, we hope this
extension fits your needs and enhances your development experience.

  1. Install Go 1.21 or newer if you haven't already.

  2. Install the VS Code Go extension.

  3. Open any Go file or go.mod file to automatically activate the extension. The
    Go status bar appears in the
    bottom right corner of the window and displays your Go version.

  4. The extension depends on go, gopls (the Go language server), and optional
    tools depending on your settings. If gopls is missing, the extension will
    try to install it. The :zap: sign next to the Go version indicates
    the language server is running, and you are ready to go.

You are ready to Go :-)    🎉🎉🎉

What's next

If you are new to Go, this article provides
the overview on Go code organization and basic go commands. Watch "Getting
started with VS Code Go"
for an explanation of how to build your first Go
application using VS Code Go.

Feature highlights

  • IntelliSense - Results appear for symbols as you type.
  • Code navigation - Jump to or peek at a symbol's declaration.
  • Code editing - Support for saved snippets, formatting and code organization,
    and automatic organization of imports.
  • Diagnostics - Build, vet, and lint errors shown as you type or on save.
  • Enhanced support for testing and debugging

See the full feature breakdown for more details.

(Code completion and Signature Help)

In addition to integrated editing features, the extension provides several
commands for working with Go files. You can access any of these by opening the
Command Palette (Ctrl+Shift+P on Linux/Windows and Cmd+Shift+P on Mac), and
then typing in the command name. See the
full list of commands provided by this
extension.

(Toggle Test File)

⚠️ Note: the default syntax highlighting for Go files is provided by a
TextMate rule embedded in VS
Code, not by this extension.

For better syntax highlighting, we recommend enabling
semantic highlighting
by turning on Gopls' ui.semanticTokens setting.
"gopls": { "ui.semanticTokens": true }

Setting up your workspace

The VS Code Go extension supports both GOPATH and Go modules modes.

Go modules are used to manage dependencies in
recent versions of Go. Modules replace the GOPATH-based approach to specifying
which source files are used in a given build, and they are the default build
mode in go1.16+. We highly recommend Go development in module mode. If you are
working on existing projects, please consider migrating to modules.

Unlike the traditional GOPATH mode, module mode does not require the workspace
to be located under GOPATH nor to use a specific structure. A module is
defined by a directory tree of Go source files with a go.mod file in the
tree's root directory.

Your project may involve one or more modules. If you are working with multiple
modules or uncommon project layouts, you will need to configure your workspace
by using Workspace Folders. See the
Supported workspace layouts documentation for more information.

Pre-release version

If you'd like to get early access to new features and bug fixes, you can use the
pre-release extension. Following the vscode's convention,
we use the minor version of the extension version number to distinguish stable
and pre-release versions (0.ODD_NUMBER.patch for pre-release, 0.EVEN_NUMBER.patch
for stable release).

To install the pre-release version, use the drop-down list
to select "Install Pre-Release Version", or if already installed the Go extension,
use the "Switch to Pre-Release Version" option in the Visual Studio Code
extension management page. For more details about this mechanism, see the
Visual Studio Code's documentation.

Telemetry

VS Code Go extension relies on the Go Telemetry to
learn insights about the performance and stability of the extension and the
language server (gopls).
Go Telemetry data uploading is disabled by default and can be enabled
with the following command:

text
go run golang.org/x/telemetry/cmd/gotelemetry@latest on

After telemetry is enabled, the language server will upload metrics and stack
traces to telemetry.go.dev. You can inspect what
data is collected and can be uploaded by running:

text
go run golang.org/x/telemetry/cmd/gotelemetry@latest view

If we get enough adoption, this data can significantly advance the pace of
the Go extension development, and help us meet a higher standard
of reliability. For example:

  • Even with semi-automated crash
    reports

    in VS Code, we've seen several crashers go unreported for weeks or months.
  • Even with a suite of
    benchmarks
    ,
    some performance regressions don't show up in our benchmark environment (such
    as the completion bug mentioned below!).
  • Even with lots of great
    ideas

    for how to improve gopls, we have limited resources. Telemetry can help us
    identify which new features are most important, and which existing features
    aren't being used or aren't working well.

These are just a few ways that telemetry can improve gopls. The telemetry blog
post series
contains many more.

Go telemetry is designed to be transparent and privacy-preserving. Learn more at
https://go.dev/doc/telemetry.

Support Policy

The Go extension is maintained by engineers on the
Go tools team,
who actively monitor the VS Code Go
and the Go
issue trackers.

We support only the latest stable and pre-release versions of the extension.

Supported Go and tools

The Go extension follows the Go Release Policy,
meaning that it officially supports the two most recent major Go releases.
The Go team maintains best-effort support for the last three major Go versions.

The Go extension relies on tools
like gopls and dlv for its core functionalities and they have their own release
policy and schedule. We test only against the latest versions of these tools.

In case you need to work with an older version of Go, please check
the Compatibility page and manually install the compatible version of
the extension and tools.

Contributing

We welcome your contributions and thank you for working to improve the Go
development experience in VS Code. If you would like to help work on the VS Code
Go extension, see our
contribution guide to
learn how to build and run the VS Code Go extension locally and contribute to
the project.

Code of Conduct

This project follows the
Go Community Code of Conduct. If you encounter a
conduct-related issue, please mail [email protected].

License

MIT


File: 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 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.
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.


File: 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 (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" 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: Open in new Document`

Open selected variable in a new document.

`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.

`Package Outline: Sort By Name`

Sort Package Outline symbols alphabetically.

`Package Outline: Sort By Position`

Sort Package Outline symbols by source position.

`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 for the type at the cursor using gopls.

`Go: Generate Interface Stubs (legacy)`

Generates method stub for implementing the provided interface and inserts at the cursor using impl.

`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.


File: 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


File: 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

If you are interested in fixing a bug or contributing a feature, please file an issue 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.

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).
This extension communicates with gopls using vscode LSP client library from language/goLanguageServer.ts.

For extending the language features or fixing bugs, please follow gopls's
contribution guide.

Debug Adapter (`dlv dap`)

Debugging features are implemented by Delve (dlv) and its native DAP implementation
(dlv dap).

  • 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: where native DAP implementation in Delve exists.

For extending the features of Delve, please follow Delve project's contribution guide.

The debugging feature documentation has a dedicated section for tips for development (See "Developing" section).

Developing

Setup

  1. Install node. 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 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.
  3. go run tools/installtools/main.go -- this will install all tools in the GOPATH/bin built from master/main.
  4. 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.
  1. 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 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 or skip 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 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.

  1. Start a gopls in deamon mode:
text
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:

text
...
  {
    "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 ...",
  }
...
  1. Start the extension debug session using the Launch Extension configuration.

  2. 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.

text
"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.

  2. Install all dependencies by running npm ci.

  3. Run npx vsce package. This will generate a file with a .vsix extension in your current directory.

    bash
    npm install vsce
    cd vscode-go
    npm ci
    vsce package
  4. Open a VS Code window, navigate to the Extensions view, and disable or uninstall the default Go extension.

  5. 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), or (2) through a Gerrit code review.

In either case, code review will happen in Gerrit, 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. Important things to note are:

  • You will need to sign the Google CLA.
  • Your commit message should follow the standards described on the Commit Message Wiki.
  • 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.


File: docs/debug-adapter.md

Debug Adapter

The Debug Adapter 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) to understand how the Debug Adapter acts as an intermediary between VS Code and the debugger (Delve).

This codebase is currently in flux: We are working on using Delve's native DAP implementation instead of this one. Follow along with golang/vscode-go#23 for updates on that work.

Overview

Before you begin

Before you start working on your change, please read the contribution guidelines. This document assumes that you are already familiar with the process of building, running, and sideloading 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.

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.

  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 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 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 from source successfully.

Next, follow these steps:

  1. Open an instance of VS Code that you have built from source.
  2. 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 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.

File: 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.

These debugging features are possible by using
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
is available, the Go extension is transitioning to deprecate the legacy debug
adapter in favor of direct communication with Delve via
DAP.

📣 We are happy to announce that the new dlv-dap mode of Delve
integration is enabled for local debugging by default. For
remote debugging it is the default in
pre-release versions 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.

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.
Alternatively, you can start debugging using Start Debugging (F5) command from
the Run menu or
from
the 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.

Review the Features section for an overview of
the Go Extension's debug UI and available features.

Stay up to date

Delve’s native DAP implementation
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. 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 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
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.

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,
    click "create a launch.json file"
  2. 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
    or
    workspace settings.

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.
  2. Click the Add Configuration button to invoke the snippet IntelliSense.

There are many configuration attributes (see
the Launch.json 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", 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" 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" 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
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).

    • 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 <function>[:<line>]. This sets the breakpoint in the line
    inside the function. The full syntax for function is
    .(*<receiver type>).<function_name> as specified in
    Delve’s location spec.
    Function breakpoints are shown with a red triangle in the BREAKPOINTS section.

  • Logpoints: a
    logpoint 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.

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

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,
    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
maxArrayValues Maximum number of elements read to load an array, slice or map. Only applies when using dlv-dap mode.(Default: 64) same as Launch
maxStringLen Maximum number of bytes read to load a string. Longer strings are truncated. Only applies when using dlv-dap mode.(Default: 512) 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 connectAllowed Values: "local", "remote"(Default: local)
output Output path for the binary of the debugee.(Default: "debug") n/a
outputMode When set to 'remote' captures the target program's stdout and stderr and transfers it to the client via DAP protocol's output events.Allowed Values: "local", "remote"(Default: local) 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
    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.

    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
      • 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. 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 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
    (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,
    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. 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.
    For configuring VS Code's terminal related behavior, see VS Code's
    documentation.

    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 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.

    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, 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:

    text
    GOBIN=<dir_to_install_dlv> go install github.com/go-delve/delve/cmd/dlv@latest

    If your Go version is older than 1.16:

    text
    cd $(mktemp -d)
    GO111MODULE=on GOBIN=<dir_to_install_dlv> 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.

    If you want to explicitly specify the location of the delve binary, use the
    go.alternateTools setting:

    json5
    "go.alternateTools": {
        "dlv": "<absolute path to your dlv binary>"
    }

    Remote debugging

    If you are able to use the
    Remote Development
    extensions and VS Code’s universal
    remote development capabilities,
    that is the recommended way to debug Go programs remotely. Check out
    Getting started
    section and
    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
    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 configuration is then used to connect to the debugger
    with a running target.

    The
    headless dlv server
    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
    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. If
    you need to use the legacy mode, please also see the
    legacy remote debugging documentation.

    For example, start external headless server:

    text
    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
    listening at host:port and then specify the target program via
    launch or 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 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:

    text
    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.
    • 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" 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
    or report a new issue.

    1. Read documentation and FAQs. Also check the
      Delve FAQ
      in case the problem is mentioned there.
    2. Check your launch.json configuration. Often error messages appearing in the
      DEBUG CONSOLE panel reveal issues.
    3. Update Delve (dlv) to pick up most recent bug fixes. Follow
      the instruction.
    4. 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.
    5. Capture logs and inspect them.
    6. Look at the
      existing debugging issues
      if similar issues were reported.
    7. If none of these solve your problem, please
      open a new issue.

    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 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
    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 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.

    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 do
    not use the launch.json configuration
    (Issue 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). 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 and
    updating extension.

    Please report issues in
    our issue tracker 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)

    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
    package. Follow Delve project's
    contribution guideline
    to send PRs.

    Code for integration with the Go extension is mostly in
    src/goDebugFactory.ts
    and tests are in
    test/integration/goDebug.test.ts.
    Please take a look at VS Code Go project's
    contribution guideline 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 if you encounter
    any logging-related problems.

    text
    dlv dap --listen=:12345 --log --log-output=dap
    json5
    {
        "name": "Launch file",
        "type": "go",
        "request": "launch",
        "debugAdapter": "dlv-dap",
        ...
        "port": 12345
    }

    File: 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

    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, and select 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.

    text
    "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 to switch between "dlv-dap" and "legacy" mode.
    For 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.

    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:
    • 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).
    • 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 for further details. golang/vscode-go#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 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 for further details. golang/vscode-go#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, 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). 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). 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). 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).

    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 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.

    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 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 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.

    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).

    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 or file a new issue.

    Read documentation and [common issues](#common-issues)

    Start by taking a quick glance at the common issues described below. You can also check the Delve FAQ 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 command and selecting dlv.

    Check your [launch configuration](#launch-configurations)

    Next, confirm that your launch configuration 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. 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.

    Check for multiple versions of Delve

    You might have multiple different versions of dlv installed, and VS Code Go could be using a wrong or old version. Run the 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.

    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. This is probably the issue if you see Cannot find package ".." in any of ... errors. Read more about configuring your GOPATH or file an issue report.

    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 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. See our contribution guide to learn how to run and sideload the Go extension.

    Ask for help

    At this point, it's time to look at the common issues below or the existing debugging issues on the issue tracker. If that still doesn't solve your problem, file a new issue.

    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.

    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, Microsoft/vscode-go#269 and go-delve/delve#357.

    Solution: You may have to uninstall dlv and install it manually as described in the Delve instructions.

    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 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.

    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.


    File: docs/experiments.md

    Experiments

    Pre-release versions of vscode-go include experimental features.
    These features may be individually enabled or disabled via the setting
    go.experiments.

    Test explorer

    Go Companion 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.

    File: docs/faq.md

    Frequently Asked Questions

    NOTE: Debugging 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 embedded in VS Code,
    not by this extension.

    For accurate syntax highlighting (including generics support), we recommend enabling
    semantic highlighting
    by turning on Gopls' ui.semanticTokens setting.

    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
    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, 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.

    2. Official Technical Reference & Guides (golang/website)

    Go website

    This repo holds content and serving programs for the go.dev and golang.org web sites.

    Content is in _content/ (go.dev) and tour/ (go.dev/tour).
    Server code is in cmd/ and internal/.

    To run the combined go.dev+golang.org server to preview local content changes, use:

    text
    go run ./cmd/golangorg

    The supporting programs cmd/admingolangorg and cmd/googlegolangorg
    are the servers for admin.golang.org and google.golang.org.
    (They do not use the _content/ directories.)

    Each command directory has its own README.md explaining deployment.

    JS/TS/CSS Formatting

    This repository uses eslint to format JS and TS files,
    and stylelint to format CSS files.

    See also:

    It is encouraged that all JS, TS, and CSS code be run through formatters before
    submitting a change. However, it is not a strict requirement enforced by CI.

    Installing npm Dependencies:

    1. Install docker
    2. Create a .gitignore file at repo root
    3. Add .gitignore and node_modules to .gitignore
    4. Run ./npm install

    Run ESlint

    text
    ./npx eslint [options] [file] [dir]

    Run Stylelint

    text
    ./npx stylelint [input] [options]

    TypeScript Support

    TypeScript files served from _content are transformed into JavaScript.
    Reference .ts files in html templates as module code.

    <script type="module" src="/ts/filename.ts">

    Write unit tests for TypeScript code using the jest
    testing framework.

    Run Jest

    text
    ./npx jest [TestPathPattern]

    Deploying

    Each time a CL is reviewed and submitted, the code is deployed to App Engine.
    See cmd/golangorg/README.md for details.

    Report Issues / Send Patches

    This repository uses Gerrit for code changes. To learn how to submit changes to
    this repository, see https://go.dev/doc/contribute.

    The git repository is https://go.googlesource.com/website.

    The main issue tracker for the website repository is located at
    https://go.dev/issues. Prefix your issue with "x/website:" in the
    subject line, so it is easy to find.