Problem Description
VSCode cannot run Go projects in run
mode (it can only debug in debug
mode), and the following error occurs.
The obscured part in the image is a package within the project, not a third-party package. This means that when running a Go project in run
mode, it cannot find other Go files, only the entry file.
Initial Investigation
The first thought about not finding other files is an issue with the GO_PATH. However, the project uses Go modules, allowing the creation of projects outside the GO_PATH, so this suspicion is ruled out. Next, I suspected an issue with the VSCode configuration. Each VSCode project has a .launch.json file that configures the environment when running code. Below is the .launch.json from the project.
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceRoot}/src/main.go",
"env": {},
"args": []
}
]
}
You can see that the .launch.json does not specify the working directory of the program. Could it be that the default working paths for debug
and run
modes are different? So I used os.Getwd()
in the main function to print the current path, and the results are as follows:
debug
mode: The project directoryrun
mode: The user directory
It can be confirmed that the working path in run
mode is incorrect, leading to the path not being found. Add the cwd
parameter in .launch.json and manually enter the project path.
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceRoot}/src/main.go",
"cwd": "${workspaceRoot}",
"env": {},
"args": []
}
]
}
However, after modifying .launch.json and running the program, the output working directory is still the user directory, indicating that the cwd
parameter did not take effect.
Exploring the VSCode Debug Process
At this point, the bug seems more evident, as the cwd
parameter is not taking effect, indicating an issue!
I decided to take a closer look at the VSCode debugging process using a rather brute-force method to see how VSCode runs Go programs when the run button is clicked.
package main
import "time"
func main() {
time.Sleep(10000000000)
}
After running the program, use ps -ef|grep go
to check the processes.
The three processes in the screenshot are in a parent-child relationship from top to bottom. This means that even when using run
mode in VSCode, it does not directly execute go run xxxx.go
, which is different from the behavior of other IDEs like Goland. VSCode first calls the node in the language server to execute a goDebug.js
in the Go extension (installed to support Go language projects), which then calls go run xxxx.go
. (The main file in the /tmp path is a binary file generated during the execution of go run)
Next, I checked the logic in goDebug.js
and found the code that calls go run
.
this.debugProcess = spawn(getBinPathWithPreferredGopath("go", []), runArgs, {
env,
});
Looking at the logic a few lines above, based on the parameter names, it can be inferred that the configuration in .launch.json can be accessed here. I then directly modified the js file for debugging to confirm the above inference. Since we cannot directly see the output of node goDebug.js, we debug by writing to a file.
fs.writeFile('test.log', this.debugProcess.cwd(), function (err) {}
After adding this line and running again, we can see that the test.log file has printed the working path of this process, which is the working path of go run, the user directory. At this point, the issue can be narrowed down to: the cwd
in the .launch.json file is not passed to the subprocess (go run) when node calls go run.
spawn
is a function in Node.js. Looking at the spawn documentation, we find that spawn has three parameters child_process.spawn(command[, args][, options])
. The third parameter options can specify the cwd working path. However, the code in goDebug.js
that starts the subprocess does not set cwd, only the env
parameter, which is why the run
mode cannot run Go programs.
Solution
When discovering this issue, the latest version of the VSCode Go extension was 0.13. This issue can temporarily be resolved by modifying the source code of goDebug.js. As shown in the image below, add the commented code to pass the cwd
parameter to the subprocess, resolving the issue.
Additionally, this bug has been fixed. You can refer to ISSUE #3096. While solving another issue in this ISSUE, the programmer “incidentally” fixed the cwd
issue. After the release of VSCode Go extension 0.14 (already released), updating the Go extension to the latest version will allow normal running and debugging of Go projects.
References
Debugging in Visual Studio Code