How does Go import Path works in versioned packages - go

I got kinda curious about how does Golang resolves named imports.
In example here, I got Echo as a package for my app.
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.Logger.Fatal(e.Start(":1323"))
}
As seen on the import line, Echo is actually being referenced by it's "v4" version, but Go can resolve as "echo".
I've dug around Echo's Repo and couldn't find anything explicit on how does Go can resolve this.
PS: On the past I've used it with an alias, such as:
...
import (
echo "github.com/labstack/echo/v4"
)
...
but that seems to be a workaround.

The first line of a Go file declares the package name using the package directive. This is the name that import resolves to when it is not an aliased import. You can use aliased imports when you need to disambiguate between multiple packages that have the same package name but different import paths.
The go.mod file keeps the import path of the Go package (for echo that is github.com/labstack/echo/v4). As JimB said, the package name does not need to correspond to the import path, it only does so by convention.
rsc.io/quote (source code at https://github.com/rsc/quote) explains Go package versioning and imports. You can also check these blog posts by Russ Cox explaining package versioning in Go.

When you import a package, the name will be the package name not the folder name.
In your case, as shown in the picture, the folder name is v4 but the package name is echo, so it will be resolved as echo.
It's a good and recommended convention to use the same package name as your folder name,
But folder versioning for major releases is known and valid.

Related

Conflict in repo name and module name

I created the github.com project qjson/qjson-go that contains the package name qjson that you can see here. I named the github project this way because github.com/qjson/ contains other projects for different languages (e.g. qjson-c).
Unfortunately, I get the following error when I try to import the project as github.com/qjson/qjson-go:
$ go mod tidy
go: finding module for package github.com/qjson/qjson-go
go: downloading github.com/qjson/qjson-go v0.0.0-20210128102242-170c47e2db46
github.com/xxx/xxx imports
github.com/qjson/qjson-go: module github.com/qjson/qjson-go#latest found (v0.0.0-20210128102242-170c47e2db46), but does not contain package github.com/qjson/qjson-go
I’m apparently doing it wrong. I understand that due to the import statement we are then expected to use gjson-go as package identifier.
What must I do so that the git project can be named qjson-go and the package qjson ?
I assume that one solution is to create a sub-directory named qjson inside qjson-go and move all package files in it. The user would then import "github.com/qson/qson-go/qjson". Is that correct ? Is there another solution avoiding the stutter ?
This program works as expected:
package main
import (
"fmt"
"github.com/qjson/qjson-go/qjson"
)
func main() {
fmt.Println(qjson.ErrDivisionByZero)
}
The issue is that you are using this file structure:
qjson/engine.go
qjson/errors.go
When you should just be putting them at the top level, like this:
engine.go
errors.go
So you can either fix the directory, and tag a new version, or just leave the
files as is, and change your imports to match what I have above.

Use Absolute path instead for go "fmt" in import directive

This is an instructional question and not a procedural one as simply requiring "fmt" works just fine, but when with the hello world golang file I modify it as follows
package main
import "golang.org/fmt"
func main() {
fmt.Println("Hello, world")
}
I get in response:
go:3:8: no required module provides package golang.org/fmt; to add it:
go get golang.org/fmt
I can see the fmt package in /usr/local/go/src/fmt and it mirrors the files in https://golang.org/src/fmt/
I am probably very close in the above file, what is the correct absolute path that would work to include fmt ? Thank you!
The correct absolute import path for the package is fmt.
Relative import paths start with ./ or ../. The import path fmt is an absolute import path.
Remote import paths start with a domain name. The package does not have a remote import path.
The tool chain creates a unique package for each import path. If the application could refer to the source code for the fmt package using a remote import path, the package with the remote path will be different from the standard fmt package. Every aspect of the package is unique. The code is duplicated. There is a ScanState type for each package and these types cannot be used interchangeably.
The pp cache is duplicated. And so on.
In this case, fmt is the fully qualified path. Compare the fmt docs [1] with golang.org/x/text docs [2].
Go standard library does have a go.mod [3], but trying to import std/fmt doesn't work either.
https://pkg.go.dev/fmt
https://pkg.go.dev/golang.org/x/text
https://github.com/golang/go/blob/master/src/go.mod

Golang Module problem--package xxx/xxxx is not in GOROOT

so here is what my directory is:
go
|-src
|-ppppppSample
|-newFolderOne
|-firstSample.go
|-hello.go
|-go.mod
and here is the content of hello.go
package main
import (
"fmt"
jjj "ppppppSample/newFolderOne"
)
func main() {
fmt.Println("start to test")
fmt.Println(jjj.FirstVVVV)
}
here is the content of firstSample.go
package newFolderOne
var FirstVVVV = "Im first SSSSSSSSSSSS"
and here is my go.mod's content
module mmmmmppppp
go 1.15
when giving it the cmd go run hello.go, the terminal came out with like this:
D:\Users\eien_zheng\go\src\ppppppSample>go run hello.go
hello.go:5:2: package ppppppSample/newFolderOne is not in GOROOT (C:\Go\src\ppppppSample\newFolderOne)
So here is my question:
(since I'm new for golang, I wish you guys could understand and tolerate some of my misunderstanding)
According to my understanding to Go module (maybe it's wrong), the Go module's function is gonna let some kind of online resource be downloaded to the directory GOPATH/pkg/mod instead of existing in GOROOT.
No matter which directory your project in, your project can still import those resource from GOPATH/pkg/mod if you init Go module.
But!!, in my understanding, it still can use package system to import package around project directory, in the meantime import online resource by Go module system.
How is that when I do (mod init) for hello.go, then it loses the (basic package import function) for this project?
|--src
|--sample
|--newFolder
|-firstSample.go (package xyz)
|--hello.go (package main import(xyz "sample/newFolder")
|--go mod (module sample go 1.15)
go mod should reference the root folder , here the root folder is |--sample
module sample
go v1.xx
inside hello.go;
package main
import ( xyz "sample/newFolder")
and make sure exported functins or variables use camelCase aka starts with BlockLetters.
Import packages within a module using the module's path:
package main
import (
"fmt"
jjj "mmmmmppppp/newFolderOne"
)
...
Run it on the Playground.

How do I fix VS Code error: "Not able to determine import path of current package by using cwd" for Go project

I'm following tutorials and I think I may have missed something.
I have a Go project located at:
/Users/just_me/development/testing/golang/example_server
The contents are:
main.go
package main
import "fmt"
func main() {
fmt.Println("hi world")
}
I have a ~/go directory.
go env shows:
GOPATH="/Users/just_me/go"
GOROOT="/usr/local/Cellar/go/1.12.9/libexec"
I installed the suggested packages in VSCode.
When I save my main.go I get:
Not able to determine import path of current package by using cwd: /Users/just_me/development/testing/golang/example_server and Go workspace:
/Users/just_me/development/testing/golang/example_server>
How do I fix this?
Since your package is outside of $GOPATH, you may need to create a module file.
You'll need to init your go module using
go mod init your.import/path
Change the import path to whatever you like.
This way you set the import path explicitly, which might help fix it.
The resulting go.mod file looks like this:
module your.import/path
go 1.14 // Your go version
So if the go.mod file is in the same directory as a main.go file, you can now import submodules from it:
E.g. main.go:
package main
import (
"your.import/path/somepackage" // Import package from a subdirectory. This only works if `go.mod` has been created as above
)
func main() {
somepackage.SomeMethod()
}
And in somepackage/whatever.go:
package somepackage
import "fmt"
func SomeMethod() {
fmt.Println("Success!")
}
if you are using vs code, check if the go and code runner extensions are enabled, if enabled, try disabling and enabling again, and if not, install and enable, and download all requested packages.

Go subpackage functions not imported properly

Trying to wrap my head around packages in Golang.
This is my workspace
/bin
/pkg
/src
/github.com
/esbenp
/testrepo
/subpackage
somefuncs.go
main.go
main.go
package main
import "github.com/esbenp/testrepo/subpackage"
func main() {
Somefunc()
}
somefuncs.go
package subpackage
import "fmt"
func Somefunc() {
fmt.Printf("yo")
}
I was under the impression that since Somefunc starts with an uppercase letter it would be exported for use in other files that imported it. The ouput I get in the console is.
main.go:4: imported and not used: "github.com/esbenp/testrepo/subpackage"
main.go:8: undefined: Somefunc
Can someone point me in the right direction?
You have to prefix the function by the name of the package is belongs to: subpackage.Somefunc().
In the case you have several subpackages with the same name, you have to alias them while importing them, or there will be a conflict:
import (
xapi "x/xx/xxx/api"
yapi "y/yy/yyy/api"
)
When you import a package it will be made available under its name.
To address Somefunc in your main.go you have to do
subpackage.Somefunc()

Resources