I am creating a web API.
I built my server and controller in the same file main.go.
I created another file name model.go where I declare a Person struct.
I can't export my model in main.go.
Every time I run or build I get this error :
can't load package: package .: found packages main
Is there a way to export func/const and import them in file with good path? (Like the way JavaScript works).
This is my tree:
myapp/
--main.go/
--model.go/
This is my import:
main.go
package main
import (
"encoding/json"
"log"
"net/http"
"./person"
"github.com/gorilla/mux"
)
model.go
package person
type Person struct {
ID string `json:"id,omitempty"`
Firstname string `json:"firstname,omitempty"`
Lastname string `json:"lastname,omitempty"`
Address *Address `json:"address,omitempty"`
}
var people []Person
within the same folder you must have the same package name.
When golang processes imports it loads all files under the same directory as a whole.
given the code you presented, model.go package name must be main.
You simply don t need to import model.go from main.go.
Now, there s a little thing to know about. When you will run go build/run/install, it will take the list of files passed as parameters to initialize the build process.
In your current setup that means you must pass all files composing the main package to the command line, otherwise, they will be ignored, in your case that means a build failure.
In plain text, you will do go build *.go instead of go build main.go
In the future if you want to avoid multiple source files to build, you should have a unique main.go, with the minimum code in it to initialize the program you are writing. As a consequence the content of model.go will exist within a different package (directory), and will be imported into main via an import xyz statement.
Finally, import path of the import directives must not be relative to the current working directory. They are all GOPATH/src based.
Related
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.
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.
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.
In the process of learning go I was playing around with making my own libraries. Here is what I did: in my $GOPATH/src I have two folders: mylibs and test. The test folder has a file called test.go which contains
package test
import "mylibs/hi/saysHi"
func main() {
saysHi.SayHi()
}
The mylibs folder contains another folder called hi, which has a file called saysHi.go containing:
package saysHi
import "fmt"
func SayHi() {
fmt.Printf("Hi\n")
}
So the directory structure looks like this:
GOPATH/src
test
test.go
mylibs
hi
saysHi.go
The problem is that when I try to compile test it complains saying
cannot find package "mylibs/hi/saysHi" in any of:
[...]
$GOPATH/src/mylibs/hi/saysHi (from $GOPATH)
I have deliberately made the directory structure deeper than necessary. If I make a simpler directory structure where I place saysHi.go in $GOPATH/saysHi/saysHi.go then it works.
But I don't see a reason for why this wouldn't work. Any ideas?
Generally speaking, your directory name should match the package name. So if you define
package saysHi
and want to import it with
import "mylibs/hi/saysHi"
you should place it in a structure like this:
mylibs
hi
saysHi
saysHi.go
The name of the .go file(s) inside the package makes no difference to the import path, so you could call the .go file anything you like.
To explain it a bit further, the import path you use should be the name of the directory containing the package. But, if you define a different package name inside that directory, you should use that name to access the package inside the code. This can be confusing, so it's best to avoid it until you understand where it's best used (hint: package versioning).
It gets confusing, so for example, if you had your package in the path
mylibs
hi
saysHi.go
And inside saysHi.go defined,
package saysHi
Then in test.go you will import it with
import "mylibs/hi"
And use it with
saysHi.SayHi()
Notice how you import it with the final directory being hi, but use it with the name saysHi.
Final note
Just in case you didn't know the following: your test file is called test.go, and that's fine, if it's just as an example, and not an actual test file for saysHi.go. But if it is/were a file containing tests for saysHi.go, then the accepted Go standard is to name the file saysHi_test.go and place it inside the same package alongside saysHi.go.
One more final note
I mentioned how you are allowed to choose a different package name from the directory name. But there is actually a way to write the code so that it's less confusing:
import (
saysHi "mylibs/hi"
)
Would import it from the mylibs/hi directory, and make a note of the fact that it should be used with saysHi, so readers of your code understand that without having to go look at the mylibs/hi code.
I'm writing small app following http://golang.org/doc/code.html
My directory tree looks like
-blog
-bin
-pkg
-src
-github.com
-packages_that_i_imported
-myblog
-config
routes.go
server.go
my server.go file contains following code
package main
import "..." //ommited imports
func main(){
r:= mux.InitRoutes() //function from imported package
Register_routes(r) //function from routes.go
}
And my routes.go
package main
func Register_routes(r *Router){
r.addRoute("test", "test", "test)
}
But after I do go run server.go
I'm getting following error
$ go run server.go
# command-line-arguments
./server.go:10: undefined: Register_routes
GOPATH variable points to my /blog folder
What am I missing? Why go doesn't it see files in subdirectories?
P.S. config/routes.go is part of server.go package
P.P.S I have moved routes.go to the same folder as server.go, but the error is still present
In order to use a function defined in another package, first you have to import it:
import "myblog/config"
And after that you have to refer to it by the package name:
config.Register_routes(r)
Also the package name should reflect the folder name in which it is defined. In your routes.go the package should be config. Package main is special, the main package will be compiled into an executable binary (it is the entry point of the program). See Program Execution in the language specification.
From the page you linked: Package names:
Go's convention is that the package name is the last element of the import path: the package imported as "crypto/rot13" should be named rot13.
Executable commands must always use package main.
There is no requirement that package names be unique across all packages linked into a single binary, only that the import paths (their full file names) be unique.
Check out the blog post Package names for a detailed guideline.
Note that different files of the same package have to be put into the same folder. And different files of the same package can use everything from the package without importing it and without using the package name (doesn't matter in which file it is defined). This is also true for unexported identifiers. From another package you can only access exported identifiers (their name must start with a capital letter).
Also the go naming convention is to used mixed caps rather than underscores to write multiword names, see Effective Go / MixedCaps. So the function should be named RegisterRoutes but this is not a requirement.