Question
I can not find a way to factor out some code from main.go
into a local
package when using Go modules (go version >= 1.11) outside of $GOPATH
.
I am not importing any external dependencies that need to be included into
go.mod
, I am just trying to organize locally the source code of this Go
module.
The file main.go
:
package main
// this import does not work
import "./stuff"
func main() {
stuff.PrintBaz()
}
The file ./stuff/bar.go
(pretending to be a local package):
package stuff
import "log"
type Bar struct {
Baz int
}
func PrintBaz() {
baz := Bar{42}
log.Printf("Bar struct: %v", baz)
}
The file go.mod
(command go mod init foo
):
module foo
go 1.12
When executing go run main.go
:
- If I
import "./stuff"
, then I seebuild command-line-arguments: cannot find module for path _/home/<PATH_TO>/fooprj/stuff
. - If I
import "stuff"
, then I seebuild command-line-arguments: cannot load stuff: cannot find module providing package stuff
. - If I
import stuff "./stuff"
with a package alias, then I see again:build command-line-arguments: cannot find module for path _/home/<PATH_TO>/fooprj/stuff
.
I can not find a way to make local packages work with go modules.
- What's wrong with the code above?
- How can I import local packages into other Go code inside a project defined with Go modules (file
go.mod
)?
Answer
First you have to choose a name for your project and write it to go.mod file. This name belongs to root directory of the project. Each new package you create must be located inside its own subdirectory and its name should match directory name.
go.mod:
module myprojectname
or (preferred way, see @thepudd's answer for details)
module github.com/myname/myprojectname
Then import your project's packages like:
import myprojectname/stuff
or
import github.com/myname/myprojectname/stuff
Files of package stuff
should be located inside project's stuff
directory.
You name these files as you like.
Also it's possible to create deeper project structure. For instance, you
decided to separate source code files from other ones (like app configs,
docker files, static files, etc...). Let's move stuff
directory inside
pkg
, every go file inside pkg/stuff
still have stuff
package name. To
import stuff package just write:
import myprojectname/pkg/stuff
Nothing stops you from creating more levels in the hierarchy like
github.com/myuser/myprojectname/pkg/db/provider/postgresql
, where:
github.com/myuser/myprojectname
- project name.postgresql
- package name.pkg/db/provider/postgresql
- path to the package relative to project's root.
You can read more about go modules here: https://github.com/golang/go/wiki/Modules
Check out this repository to get useful information about various patterns
used in project organizing: <https://github.com/golang-standards/project-
layout> If you go inside pkg
directory you will find out which open source
projects use pkg
directory in their structure.