Relative imports in Go - go

I have a go Project with the following directory structure
utils(pkg)
| auth.go (has a function names test1)
controllers(pkg)
| login.go (has a function names test2)
I am trying to access function test1 from login.go. Here is what I have done
import "../utils"
func test2(c *gin.Context) bool{
utils.test1()
}
But I always get Unresolved reference test1. I am new to go . Can anyone help why I am getting this error?

No there is no relative import in Go.
you should use the absolute path considering GOPATH:
The GOPATH environment variable specifies the location of your workspace. It is likely the only environment variable you'll need to set when developing Go code. To get started, create a workspace directory and set GOPATH accordingly. see: https://golang.org/doc/code.html#GOPATH
Import paths
An import path is a string that uniquely identifies a package. A package's import path corresponds to its location inside a workspace
or in a remote repository (explained below).
The packages from the standard library are given short import paths
such as "fmt" and "net/http". For your own packages, you must choose a
base path that is unlikely to collide with future additions to the
standard library or other external libraries.
If you keep your code in a source repository somewhere, then you should use the root of that source repository as your base path. For
instance, if you have a GitHub account at github.com/user, that should
be your base path.
Note that you don't need to publish your code to a remote repository
before you can build it. It's just a good habit to organize your code
as if you will publish it someday. In practice you can choose any
arbitrary path name, as long as it is unique to the standard library
and greater Go ecosystem.
Example:
This example assumes you have set GOPATH=/goworkdir in your OS environment.
File: goworkdir/src/project1/utils/auth.go
package utils
func Test1() string {
return "Test1"
}
File: goworkdir/src/project1/controllers/login.go
package controllers
import "project1/utils"
func Test2() string {
return utils.Test1()
}
File: goworkdir/src/project1/main.go
package main
import (
"fmt"
"project1/controllers"
)
func main() {
fmt.Println(controllers.Test2())
}
Now if you go run main.go you should see output:
Test1

This is now different since the introduction of go modules, from go 1.11.
Thus, if you switch to go modules, and if your module is called "m", then the idiomatic way to do relative imports in your project tree would be to use: import "m/utils" and import "m/controllers" in places where you need to import those packages in your project.
For details, see:
https://github.com/golang/go/wiki/Modules#do-modules-work-with-relative-imports-like-import-subdir
GoLand users - by default these forms of imports appear as errors in the IDE. You need to enable Go Modules integration in settings

Here is another example project structure with file contents required to import correctly:
test1/
utils/
texts.go
main.go
go.mod
with following contents:
go.mod:
module mycompany.com/mytest
go 1.15
utils/texts.go (to make a function visible from a different package, it needs to start with an uppercase letter):
package utils
func GetText() string {
return "hello world"
}
main.go (only the full import name is supported, there is no shortcut to import from the same module easier):
package main
import (
"fmt"
"mycompany.com/mytest/test1/utils"
)
func main() {
fmt.Println(utils.GetText())
}

Given this directory configuration:
.
├── controllers
│   └── login.go
├── main.go
└── utils
└── auth.go
File main.go:
package main
import "./controllers"
func main() {
controllers.Test2("Hello")
}
File controllers/login.go:
package controllers
import "../utils"
func Test2(msg string) {
utils.Test1(msg)
}
File utils/auth.go:
package utils
import . "fmt"
func Test1(msg string) {
Println(msg)
}
Result works:
$ GO111MODULE=auto go build -o program main.go
$ ./program
Hello
So what you wanted to do works. The only difference is that I've used upper case function names, because it's required to export symbols.

I think you can just crate a vendor directory next to your source file, which acts like a relative GOPATH, and then create a relative symlink, which links to the package you want to import inside the vendor directory, and then import the package as if the vendor directory is your $GOPATH/src/.

It's possible as of Go 1.16, although still not as straightforward as it could be, by editing the go.mod file to resolve the package name to a relative path:
if you have a hello and a greeting packages side by side (hello contains main.go):
<home>/
|-- greetings/
|--go.mod <- init this as infra/greetings
|--greetings.go <- let's say that this package is called greetings
|-- hello/
|--go.mod <- init this as whatever/hello
|--main.go <- import infra/greetings
then edit hello's go.mod file and get the package:
go mod edit -replace infra/greetings=../greetings
go get infra/greetings
go mod tidy
There's a full example in the official documentation but hey, this might change again in the next version of Go.

Related

How to import a single go file in golang? Unable to import go file

Trying to import a file go file but unable to do so.
I have one main file:
main/
main.go
go_single_file.go
package main
import (
"./go_single_file"
)
func main() {
}
and go_single_file:
package go_single_file
func hello() bool{
return true
}
when i try to import go_single_file in my main file i get some sort of import error.
I am doing something wrong but not sure what.
If i make a separate package and import it then it works but not if it's in same folder.
Can anyone tell how can i import a go file from same folder.
In Golang files are organized into subdirectories called packages which enables code reusability.
The naming convention for Go package is to use the name of the directory where we are putting our Go source files. Within a single folder, the package name will be same for the all source files which belong to that directory.
I would recommend you to use go modules and your folders structure should be like this.
.
├── main.go
├── go.mod
├── go_single_file
│ └── go_single_file.go
In your go_single_file.go you are not using exported names for the function hello. So your file inside the go_single_file/go_single_file.go would look like this.
package go_single_file
func Hello() bool{
return true
}
Your main file would like this
package main
import (
"module_name/go_single_file"
)
func main() {
_ = go_single_file.Hello()
}

Project structure and importing packages

I'm just starting to learn Go and I'm wondering how to best organize my project and import packages. I created a project at $GOPATH/src/my_project. It contains the file main.go and the folder foo containing the file bar.go.
$GOPATH/src/my_project
main.go
foo/
bar.go
My main.go looks as follows
package main
import (
"./foo"
"fmt"
)
func main() {
fmt.Println("Main")
foo.Baz()
}
Here is the foo.go
package foo
import "fmt"
func Baz() {
fmt.Println("Baz")
}
It works the way I expect it to, but I wonder if this is really the right way to structure a project and import packages, because most tutorials only import packages from github and never from local.
Thanks for your answers..
Relative imports are possible in Go but they are not encouraged to be used.
Instead you always use the full path of the package. In your case that would be my_project/foo. This is is relative to the GOPATH/src folder.
However, since we have Go modules now which make things a tiny bit more complicated to start with but have a lot of advantages in the long run.
Just earlier today I gave a step by step guide on how to set up a new project with Go modules: After go install the import doesn't recognize the package
The module name in this guide is the basis for your project then and all paths in the module build on that path. Let me give an example:
Let's say you name your module github.com/yourName/myProject. Then you can import the subpackage foo with github.com/yourName/myProject/foo.
Note: The module path should be the same as the git URL, that way you can just get the module with go get. If you don't plan on ever uploading the project to github or another git URL, you should still choose a unique name. Starting with a domain you own is a good idea -- for uniqueness.

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.

Call function in another files

I don't know how I can use function in another file.
my project architecture:
.
├── main.go
└── src
└── function.go
1 directory, 2 files
main.go
package main
import "src/funcrion"
func main() {
funcrion.Display();
}
function.go
package src
import "fmt";
func Display() {
fmt.Println("Hello World");
}
For start my project I use:
go run main.go
error:
main.go:3:8: cannot find package "src/funcrion" in any of:
/usr/local/opt/go/libexec/src/src/funcrion (from $GOROOT)
/Users/clementbolin/go/src/src/funcrion (from $GOPATH)
In first, I want to resolve this problem. In second time I want to know what is the best option for compile a real project with more 10 files for example, do I need to use Makefile? Or like in Rust go has package manager?
When you do import "src/funcrion" the go compiler will try to search for this in GOPATH and GOROOT, as you see in your error message. It does not try to search in the current folder. Since it doesn't find a package with that name in either GOPATH or GOROOT, it gives you that error.
A good way to reference "the current folder" would be using go modules. On the root of your project do $ go mod init myproject. (replace myproject for a more appropriate name for your project)
After you do that, you can use "myproject" to reference the project folder in package names, like:
package main
import "myprject/src"
func main() {
src.Display();
}
Also note that the import goes only up to the package name and not the file name. So, in your case, you shouldn't do import myproject/src/function just because you have a function.go file inside a src package.
And since your Display function is inside the src package, you refer to it simply with src.Display() after importing the package. No need to specify the name of the file anywhere.
You can read more about go modules here: https://blog.golang.org/using-go-modules
Another tip is to not use src as a package name. In Go, it's common to not have a "src" folder, and as a package name is also not very good. For instance, see the line that reads src.Display(). Instinctively, i would read this as something like "the Display of the source", which has no meaning. But if instead of src you name your package text, that same line would read text.Display() which would read as "display some text", which is more accurate and meaningful to what the function is doing.
I believe the package name is src but I see you are trying to import src\funcrion There is no such package called funcrion.
I think you should just do something like this main.go
package main
import "src"
func main() {
src.Display();
}
or if you would like to call your src package as funcrion, then just import it like below,
import funcrion "src"
And make sure your file structure is as below and inside $GOPATH
Users
└── clementbolin
└── go
└── src
├── main.go
└── src
└── function.go

Does it make sense to have two packages in the same directory?

I have a project that provides a library (exports some funcs) and also must provide a command-line interface (there must be an executable file).
Example of directory structure:
whatever.io/
myproject/
main.go
myproject.go
The go compiler needs the package main and func main to start execution. My library needs the package myproject where I put stuff on it. This is what the go tool says when I am building another project that tries to import myproject:
main.go:5:2: found packages myproject (myproject.go) and main (main.go) in $GOPATH/src/whatever.io/myproject
So I believe there is no way to do it.
Should I move the library or the CLI to another package?
Just move your packages inside a new folder within the same directory of main.go.
Remember to import the new package from the reference of the $GOPATH.
Example:
user#user:~/p/go/test/so-multipack$ ls -R
.:
a main.go
./a:
a.go
user#user:~/p/go/test/so-multipack$ cat main.go
package main
import (
"../so-multipack/a"
)
func main(){
a.Hello()
}
user#user:~/p/go/test/so-multipack$ cat a/a.go
package a
import (
"fmt"
)
func Hello(){
fmt.Println("hello from a")
}
user#user:~/p/go/test/so-multipack$ go run main.go
hello from a
user#user:~/p/go/test/so-multipack$ go build
user#user:~/p/go/test/so-multipack$ ls
a main.go so-multipack
user#user:~/p/go/test/so-multipack$
Useful link:
go build vs go build file.go
You cannot have two packages per directory, hence the error. So the solution as #Larry Battle said to move your myproject.go to a new directory.
From How to write go code
Go code must be kept inside a workspace. A workspace is a directory
hierarchy with three directories at its root:
src contains Go source files organized into packages (one package per directory),
pkg contains package objects, and
bin contains executable commands.
In most cases, no. However, there is an exception for unit tests.
Working Example:
Here are 2 different packages (mypackage and mypackage_test) in 1 directory (mypackage). The compiler will not complain about this.
mypackage folder:
mypackage/
foo.go
foo_test.go
mypackage/foo.go:
package mypackage
func Add(a int, b int) int {
return a + b
}
mypackage/foo_test.go:
package mypackage_test
// Unit tests...
Rules:
The 2 packages must have the following names:
NameOfDirectory.
NameOfDirectory + _test.
The names of the files in the _test package must end with _test.go
If you're receiving a confusing compiler error along the lines of found packages "foo" and "bar", you've probably broken one or more of these rules.
You can't have two golang files in one directory with two packages. So you need to move main.go out of myproject.
the directory structure before move
whatever.io/
go.mod
myproject/
main.go
myproject.go
After move
whatever.io/
go.mod
main.go
myproject/
myproject.go
And you need to change your main.go's import path. If the module name is aaa
Before
import "aaa"
Need change to this
import "aaa/myproject"

Resources