Go linter in VS code not working for packages across multiple files? - go

I have installed the Go extension (version 0.11.4) in Visual Studio Code on MacOS:
However, I find that the linter does not 'pick up' functions defined in the same package, but in different files. For example, if I create in the same directory a file foo.go with
package foobar
import "fmt"
func main() {
fmt.Println(SayHello())
}
and a file bar.go with
package foobar
func SayHello() string {
return "Hello, world!"
}
then in foo.go I get a linter error that SayHello is an undeclared name:
I've read about a similar issue here (https://github.com/golang/lint/issues/57), but since that issue is five years old I figured it might be fixed by now? Or does golint simply not work across multiple files?

[The original answer is outdated; here is up-to-date information provided by the vscode-go maintainers. The updated answer is now marked as "Recommended" in the Go collective]
The plugin has changed a lot since 2019.
In 2021, Go Modules became the default which may have changed how the program is built and analyzed.
The vscode-go plugin uses gopls as the language server by default. Note that in 2019, there were two different language servers and gopls was still in experimental mode.
golint was deprecated.
If you still have a similar issue, it's likely that you are seeing a different problem.
Please check the followings:
Do you have go.mod? Otherwise, initialize your working module and restart the language server or reload the window.
Is the go.mod file in the root directory of your workspace? See gopls workspace setup
guide for complex setup.
Do you use build tags or other build constraints? Then see issue 29202. You may need to configure "go.buildTags" or "go.buildFlags".
If you expect lint errors from linters like staticcheck, golangci-lint, ..., check "go.lintOnSave" is set to the right scope.
If you notice that restarting the language server ("Go: Restart Language Server" command) fixes your issue, that's a gopls bug. Please consider to file an issue in github.com/golang/vscode-go following the troubleshooting guide.
Otherwise, please open a new question with details.
----- Original answer -------
I faced same problem. I found that I got into this problem after enabling "Go language server" which is an experimental feature. I disabled it in VS code settings->Go Configuration and after that the problem went away.

Update VS Code Go Tool might help.
Command + Shift + P -> Go: Install/update tools
Install all tools and restart VS Code.
May 2022 update:
This solution only works if you haven't installed the helper tools. Normally after you installed these packages it'll work right away with the default configuration, if you still have a problem, take a look at the answer above.

The cause of this warning for me was the setting go.lintOnSave, which was set to file. Changing the value to package made the linter correctly pick up the types defined in other files.

For people who ended up here:
The plugin has changed a lot since 2019.
In 2021, Go Module became the default which may have changed how the program is built and analyzed.
The vscode-go plugin uses gopls as the language server by default. Note that in 2019, there were two different language servers and gopls was still in experimental mode.
golint was deprecated.
If you still have a similar issue, it's likely that you are seeing a different problem.
Please check the followings:
Do you have go.mod? Otherwise, initialize your working module and restart the language server or reload the window.
Is the go.mod file in the root directory of your workspace? See gopls workspace setup
guide for complex setup.
Do you use build tags or other build constraints? Then see issue 29202. You may need to configure "go.buildTags" or "go.buildFlags".
If you expect lint errors from linters like staticcheck, golangci-lint, ..., check "go.lintOnSave" is set to the right scope.
If you notice that restarting the language server ("Go: Restart Language Server" command) fixes your issue, that's a gopls bug. Please consider to file an issue in github.com/golang/vscode-go following the troubleshooting guide.
Otherwise, please open a new question with details.

Update Install/update tools for GO
Open your code as main project in VS Code and avoid multiple projects/workspace in the same VS Code.
**
Single Project VS Code
**
**
Avoid Multiple Project in VS Code
**

If you run across this and are NOT using modules, then adding "go.useLanguageServer": false will disable gopls and return you to your former environment. (meaning vscode will now recognize functions and structures defined in multiple files in the same package)

In my case it was a missing go.mod file. I fixed with the following command:
go mod init example.com/myProject/myModule
Of course you should use a more reasonable module name.

Make clean uninstall of vscode and then it's work fine again...
add sudo if you needed to
rm -rf $HOME/Library/Application\ Support/Code
rm -rf $HOME/.vscode
Remove vscode from application
Download vscode and install again

One possible reason:
If you are referencing a function/variableis declared in a test file (*_test.go) from a non test file, this error would be thrown.

In my case, I just restarted VS Code and the error went away.

After almost pulling my hair out, I found that linting was working but I had many files with errors. I haven't yet found the hierarchy followed but fixing problems in one file subsequently led to it correctly linting another file. I think it follows the execution tree, although I haven't validated this.
I found this annoying as it can mistakenly lead you to think that linting is not working, while in fact, it's lining a file that you're not currently focussed on, especially if you have generated files that you're not interested in.

Another solution might be that you need to have the folder opened in VS Code with the go.mod file included. So you might have a folder structure that looks like workspace/application/modules/xyz.go. If you have the go.mod file in the application folder and modules is the folder you have open in VS Code it will complain.

I came across this issue by having the go extension installed, and attempting to utilize the same package name with a module under a different directory.
Files at Root: main.go, a.go, and go.mod
Sub-directory: nested/b.go
Problem: Attempting to label b.go as package main when it is under a different directory.
Solutions:
Move b.go up to project root and retain package name; all works as expected,
or
Change package name of b.go from package main to package nested, then add imports for b.go to main.go via:
// main.go
package main
import "example/nested"
func main() {
A()
nested.B()
}
and b.go:
// b.go
package nested
import "fmt"
func B() {
fmt.Println("Hello from B")
}

Related

VS Code showing me "Error loading workspace: found module "main.go" twice in the workspace"

I am using the primary GO extension.
I use VS code a lot, now I'm learning GO lang.
And when I open VS Code every time I'm getting this:
Error loading workspace: found module "main.go" twice in the workspace.
While running the code it's giving the right output.
I don't know how to fix this.
Anybody, help me with this error.
It would be better to open in VSCode only one folder with its own go.mod project.
A workspace with multiple go.mod/project should be supported with 1.18
The go command now supports a "Workspace" mode.
If a go.work file is found in the working directory or a parent directory, or one is specified using the -workfile flag, it will put the go command into workspace mode.
In workspace mode, the go.work file will be used to determine the set of main modules used as the roots for module resolution, instead of using the normally-found go.mod file to specify the single main module.
As described in "How to make VScode Go work in a Multi-Module Repo" from Varun Kumar, this used to work:
If you want to work with all the nested modules in a single workspace, there is an opt-in module feature that allows to work with multiple modules without creating workspace folders for each module. Set this in your settings -
"build.experimentalWorkspaceModule": true
But as per september 2022 is deprecated.
See more at gopls documentation "Setting up your workspace".

How to proper configure "Go Build" and what are the differences between Run Kind

I am new to Go language and also to the IDE GoLand so I am sorry if this is very basic.
I am currently trying to configure Run Kind for package for all my files, the problem is I cannot seem to get the configuration straight, I get this error:
"can't load package: package Course: unknown import path "Course": cannot find module providing package Course"
My GOROOT is the standard in C: and GOPATH is in my directory of workplace with the folders: scr, bin and pkg. Inside scr is course folder with training files for Go.
I have tried to google every option on how to properly configure the go Build configuration, I might be missing to install packages not sure to be honest, I have installed the gotools and everything from golang.org, and tried following the guide from GoLand in JetBrains but no luck in properly configuring package, or Dir options.
I can create a go Build for each file using Run Kind: File, but I want to create one for all the files inside the folder not one each time I want to run one.
Also I have no idea what -i in Go tool arguments means.
I believe what you need to do is simply enable go module integration. Find the setting at File | Settings | Go | Go Modules (vgo). In that panel also make sure Vgo executable is set to your Project SDK. If it's still not working, enabling the vendor experiment option at File | Settings | Go | Build Tags & Vendoring may help. Be sure your project specific settings aren't overriding these values as well.

View package documentation locally in a browser

I want to see locally how my package documentation will look. That is, I want to see the same kind of thing you see on godoc.org, but locally.
I have a simple example folder locally, but I can't get it to work. It correctly outputs text documentation:
~/code/go/gonotes (master) $ godoc .
PACKAGE DOCUMENTATION
package gonotes
import "."
FUNCTIONS
func Blah()
Here is header
Blah is function being use to test:
- go documentation
- blah like things
It is nice
But if I run godoc -http=:6060, and navigate to http://localhost:6060/, I see essentially the same content I'd see on the golang.com homepage. http://localhost:6060/gonotes displays
lstat $GOROOT/gonotes: no such file or directory
Am I misunderstanding how the -http works? Is there any way to preview the http version of my docs locally?
UPDATE
I was able to get it to appear by copying the files into src/gonotes and then running:
GOPATH=/Users/jonah/code/go/gonotes godoc -http=:6060
so that the actual files were available at /Users/jonah/code/go/gonotes/src/gonotes.
This has the side effect of not showing any of the Third part libs installed in my default GOPATH, so I'd still like to find a solution that just allows me to add the current directory, as is, without adding src/curdir to it, and still have it show up.
In GOPATH mode
godoc -http will serve doc of all available packages, including the standard library. Worry not, your own packages are amongst them, just look again. As a shortcut, just type http://localhost:6060/pkg/your/package.
In module-aware mode
GOPATH and modules are mutually exclusive, see Go Modules does not recognize files under GOPATH. The godoc tool is not module-aware, and it is being deprecated (see deprecation warning), so for now if you want to see your package docs of modules locally in godoc, you have to resort to putting their sources in an src folder.
"Workaround" for seeing docs of module's:
Put the repo in a folder like /some/folder/src
Start godocs with godoc -goroot=/some/folder -http=:6060
See related issue: support Go modules
Also groups discussion: Is the go 1.11 godoc tool 'module-aware'?

Set Go variable with ldflags conflicts with vendor folder

I'm currently developing a small Go app and I want to set a specific variable (like Version, GitCommit, BuildID...etc.) at build or runtime (with go build or go run) by using the -ldflags option.
Because in my company we have several projects with the same base, I decided to extract the code with these variables in a separate "info" module which could be imported in every project.
Here's my problem, say I'm running the app like this:
go run -ldflags "-X git.mycompany.com/utils/info.Version=1.0.0" app.go
This works well, and the variable is set correctly even though the variable is not part of the "main" app but in a dependency.
Then I decided to deploy the app so I used the new dep tool to generate the vendor folder.
Therefore, the "info" dependency is now in: vendor/git.mycompany.com/utils/info
Now when I run the same command as above, the said variable (Version) is not set anymore.
Am I missing something here ?
As soon as I delete the vendor folder, everything works fine again. It's like this vendor folder is conflicting with the -ldflags option or something.
Thanks in advance!
We had exactly the same problem, after lots of research we stumbled upon the solution in a comment to GitHub issue: cmd/link: -X doesn't work for vendored packages.
Solution: the full path name, relative to $GOPATH should be specified.
It works when developing git.mycompany.com/utils/info because the full path is correct.
It doesn't work for vendored dependencies because the full path from $GOPATH would be like git.mycompany.com/name-of/package/vendor/git.mycompany.com/utils/info.Version=1.0.0
Unfortunately, no documentation seem to be present about this ( for further info look at the issue ) but as Dave Cheney points out in a comment:
this is a side effect of the language way vendoring is implemented

Go build error: no non-test Go files in <dir>

Getting an error when trying to run go build ./... from my $GOPATH/src .
no non-test Go files in <dir>
The error is correct there are no test files in <dir> but why is that causing a compile error? Is it a bug?
I don't think this is a bug, unless you see somewhere in the docs that contradicts this behaviour you should probably close the issue you've created.
Tests in go normally live in the package they are testing. You have made a new package with package main at the top (invalid if you also have main elsewhere), and then have included no go source files in that tests/main package (invalid as package has no go source files apart from tests, which the compiler complains about explicitly).
Possible solutions for you (assuming this isn't just a hypothetical question):
Move tests for main to test_main.go (this is what readers will
expect)
Add doc.go file to your tests pkg and call it package tests in
both files
The reason for putting tests in the same package is to ensure they have access to the entire package, if you want to split them to another package you'll find you have to test as an external user of the pkg - this may be painful. Main is also a special case as well as you don't normally import it.
Calling it a bug… the build shouldn't fail if the tests compile. Filed here: https://github.com/golang/go/issues/22409
The bug I filed was a duplicate of https://github.com/golang/go/issues/8279 looks like it was broken in 1.3.
First, check your $GOPATH has been set correctly. Learn more at here.
Then, check if any '_' in your file name. Remove these '_'s and try again.
;-)

Resources