Go local module import can't be resolved by IDE linter - go

The code compiles fine, but when using the replace directive for mapping package name to a local directory, the Go linter can't pick this up.
I've tried this on both VSCode & Goland, both has the lint error as shown below. The image is extra information, all code & error messages are shown below in text format.
Repository: https://github.com/webberwang/go-lint-error
This is the folder structure:
/core
/calc
math.go
go.mod
/main
app.go
go.mod
// main/app.go
package main
import (
"fmt"
"github.com/codelabstudios/core/calc" <- ERROR "Cannot resolve directory 'core'"
)
func main() {
result := calc.Add(1, 2) <- ERROR "Unresolved reference 'Add'"
fmt.Println("calc.Add(1, 2) => ", result)
}
// main/go.mod
module github.com/codelabstudios/main
go 1.14
require github.com/codelabstudios/core v0.0.0-00010101000000-000000000000
replace github.com/codelabstudios/core => ../core
// core/calc/math.go
package main
import (
"fmt"
"github.com/codelabstudios/core/calc"
)
func main() {
result := calc.Add(1, 2)
fmt.Println("calc.Add(1, 2) => ", result)
}
// core/calc/go.mod
module github.com/codelabstudios/core
go 1.14

After some digging, I found out that the "replace" directive is part of the Vgo proposal (the V stands for versioning). This was merged with Go in 1.11.
To fix the local module import error, we just need to enable "Vgo Integration" in the IDE.

Related

Go: import package from the same module in the same local directory

I want to create new package mycompany that will be published on Github at github.com/mycompany/mycompany-go (something similar to stripe-go or chargebee-go for example).
So I have created a folder ~/Desktop/mycompany-go on my MacOS. Then inside that folder I run go mod init github.com/mycompany/mycompany-go.
I have only these files in that local folder:
// go.mod
module github.com/mycompany/mycompany-go
go 1.19
// something.go
package mycompany
type Something struct {
Title string
}
// main.go
package main
import (
"github.com/mycompany/mycompany-go/mycompany"
)
func main() {
s := mycompany.Something {
Title: "Example",
}
}
However I get this error:
$ go run main.go
main.go:4:3: no required module provides package github.com/mycompany/mycompany-go/mycompany; to add it:
go get github.com/mycompany/mycompany-go/mycompany
I think that this is a wrong suggestion, because I need to use the local version, in the local folder, not get a remote version.
Basically I need to import a local package, from the same folder, from the same module.
What should I do? What's wrong with the above code?
You can't mix multiple packages in the same folder.
If you create a folder mycompany and put something.go inside it, that should fix the problem
The Go tool assumes one package per directory. Declare the package as main in something.go.
-- main.go --
package main
import "fmt"
func main() {
s := Something{
Title: "Example",
}
fmt.Println(s)
}
-- go.mod --
module github.com/mycompany/mycompany-go
go 1.19
-- something.go --
package main
type Something struct {
Title string
}
Runnable example: https://go.dev/play/p/kGBd5etzemK

go malformed import path empty path element

Trying to run
go mod init `pwd`
On a trivial example
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
// Echo instance
e := echo.New()
// Route => handler
e.GET("/", func(c echo.Context) error {
return c.HTML(http.StatusOK, "Hello, World!\n")
})
// Start server
e.Logger.Fatal(e.Start(":1323"))
}
Gives an error
go malformed import path (path to file) empty path element
Yet if I create a manual go.mod like this
module <path>
go 1.12
require github.com/labstack/echo/v4 v4.1.6
Then I can build / run the code normally.
Any idea why go mod init fails?
Mostly for future reference as creating the go.mod solves the immediate issue.
Try initializing the modules in the console. The syntax for that is go mod init <mod_name> where mod_name can be github.com/labstack/echo/v4.
As suggested above, go mod init but without / at the beginning of your path works. Perhaps outside of GOPATH relative paths should be used instead of absolute paths(?)

GOSwagger implementation for imported packages

I'm created a project structure like,
main.go and foo/bar.go
In main.go, imported foo package and used as foo.functionName(). Now i need to write swagger document in bar.go. When i did, ended with the following error message,
unable to determine package for /PATH_TO_PROJECT/foo/bar.go
Ensure in foo/bar.go the package declared is package foo. Then the function you want to access in the main.go file should start with a capital letter. i.e.
foo/bar.go
package foo
// PrintBar with extra txt
func PrintBar(txt string) string {
return "bar with txt " + txt
}
Then in main.go
package main
import (
"fmt"
"github.com/username/project/foo"
)
func main() {
fmt.Println("in main.go")
fmt.Println(foo.PrintBar("from main.go"))
}
Try enabling Debug mode for swagger by adding DEBUG=1 in front of your swagger command. This should print you what are the paths considered.
If you look at the source code where this error is thrown, you will see this error only happens when file is not in the $GOPATH. Double check that you have the program under $GOPATH/src.

Structuring local imports without GitHub in Golang

I'm building a simple app and after reading the doc on structuring go applications, I'm still confused.
I want this structure:
practice
models (packaged as models)
a
b
routers (packaged as routers)
a
b
app.go
Inside of app.go, I have the following:
package main
import (
"net/http"
// I have tried the following:
"practice/models/a"
"practice/models/b"
"practice/models"
"$GOPATH/practice/models/a"
"$GOPATH/practice/models/b"
"$GOPATH/practice/models"
...
)
func main() {
http.HandleFunc("/a", AHandler)
http.HandleFunc("/b", BHandler)
http.ListenAndServe(":8080", nil)
}
The A and B models look like this:
package models
import "net/http"
func AHandler(w http.ResponseWriter, r *http.Request) {
// code
}
Two questions:
What in the world is the right way to import these files? Do I really have to push them to github in order to be able to reference them? I understand the $GOPATH is the namespace for the entire go workspace on a local machine. My $GOPATH is set to include this directory.
Do I need to define a main method inside of these files? Can I just export a single function and have that be the handling function?
I have consulted the docs
See How to Write Go Code.
Use this directory structure:
- practice
- go.mod
- app.go
- models
- a.go
- b.go
- routers
- a.go
- b.go
where go.mod is created with the command go mod init practice where practice is the module path.
Import the packages as follows:
import (
"practice/routers"
"practice/models"
...
)
Use the imported packages like this:
func main() {
http.HandleFunc("/a", models.AHandler)
http.HandleFunc("/b", models.BHandler)
http.ListenAndServe(":8080", nil)
}
You do not need to push to github.com, even if you use github.com in the module path.
The main function in the main package is the entry point for the application. Do not define main functions in packages other than main.
What follows is the original answer based on GOPATH workspaces:
See How to Write Go Code.
Create your directory structure under $GOPATH/src.
$GOPATH
src
practice
models
routers
Import the packages as follows:
import (
"practice/routers"
"practice/models"
...
)
Use the imported packages like this:
func main() {
http.HandleFunc("/a", models.AHandler)
http.HandleFunc("/b", models.BHandler)
http.ListenAndServe(":8080", nil)
}
You do not need to push to github.com, even if you use 'github.com' in the file path.
The main function in the main package is the entry point for the application. Do not define main functions in packages other than main.
I think the other answer is out of date, you don't need to use GOPATH anymore.
Run:
go mod init yellow
Then create a file yellow.go:
package yellow
func Mix(s string) string {
return s + "Yellow"
}
Then create a file orange/orange.go:
package main
import "yellow"
func main() {
s := yellow.Mix("Red")
println(s)
}
Then build:
go build
https://golang.org/doc/code.html

My main.go file cannot see other files

I need some help understanding what is wrong with my file layout in a simple web application.
$GOPATH/src/example.com/myweb
I then have 2 files:
$GOPATH/src/example.com/myweb/main.go
$GOPATH/src/example.com/myweb/api.go
Both files have:
package main
The api.go file looks like:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
type API struct {
URI string
Token string
Secret string
client *http.Client
}
...
My main.go file looks like:
package main
import (
"github.com/gorilla/mux"
"html/template"
"net/http"
)
var (
templates = template.Must(template.ParseFiles("views/home.html", "views/history.html", "views/incident.html"))
api = API{
URI: "http://localhost:3000",
Token: "abc",
Secret: "123",
}
)
func renderTemplate(w http.ResponseWriter, tmpl string, hp *HomePage) {
..
..
}
func WelcomeHandler(w http.ResponseWriter, r *http.Request) {
..
..
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/", WelcomeHandler)
r.PathPrefix("/assets/").Handler(
http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/"))))
http.ListenAndServe(":9000", r)
}
In the code I excluded, I basically use structs that are defined in my api.go file, and I get this error when doing:
go run main.go
# command-line-arguments
./main.go:16: undefined: API
./main.go:23: undefined: User
What exactly am I doing wrong here?
I tried changing the package name in api.go to myweb but that didn't help.
Am I suppose to use the package name myweb? Is just 1 file suppose to have main?
You're compiling only the main.go file. You should use:
go run main.go api.go
Or:
go run *.go
If you're writing a complex application, you might add everything to packages in subdirectories and have a single main.go file. For instance, etcd has an etcdmain subdirectory/package along with other subdirectories/packages. Something like:
/alarm
/auth
/cmd
/etcdmain
...
And the main.go file is simply:
package main
import "github.com/coreos/etcd/etcdmain"
func main() {
etcdmain.Main()
}
You are using golang workspace project, which is good for the structure for your application and it also standardize.
When we use the golang workspace, you can not run single go file. You need to call go build / go install.
Install
go install example.com/myweb
The command above will compile your main package on example.com/myweb. And the myweb executable binary will be placed on the GOPATH/bin. And you can run it manually.
Build
go build example.com/myweb
The command is similar to go install but the binary executable file will be placed on the current directory when you call the command, instead of on GOPATH/bin (unless your current directory is GOPATH/bin).
For more information please check this link.

Resources