I'm having issues with go's new module system, as I'd like to define a local module and import it in the main program. The local package resides in a folder of the main package/root folder. Imagine the following project structure outside the $GOPATH
.
./main.go
package main
import "fmt"
import "example.com/localModule/model"
func main() {
var p = model.Person{name: "Dieter", age:25}
fmt.Printf("Hello %s\n", p.name)
}
./model/person.go
package model
type Person struct {
name string
age int
}
In the root folder I initialized a module by calling
go mod init example.com/localModule
In the model/
folder I then initialized the submodule by calling
go mod init example.com/localModule/model
In the root folder calling the following commands fail.
$ go get
go build example.com/localModule/model: no Go files in
$ go build
main.go:4:8: unknown import path "example.com/localModule/model": cannot find module providing package example.com/localModule/model
The error message for go get is cut off, I din't parse it wrongly.
I do not plan on pushing the module to a server and and just needed a way of referencing the local package model
, so I chose example.com/localModule/
and example.com/localModule/model
respectively.
I'm using go1.11 darwin/amd64
on a Macbook running MacOS 10.13.6.
You can have local "sub" modules like you ask for by adding a require statement and a matching replace statement with a relative file path in go.mod.
In the "root" ./go.mod:
module example.com/localModule
require example.com/localModule/model v0.0.0
replace example.com/localModule/model v0.0.0 => ./model
The reason you are getting this error is because you have defined two modules that do not know how to find each other on your local disk.
$ go build
main.go:4:8: unknown import path "example.com/localModule/model":
cannot find module providing package example.com/localModule/model
replace
You can add a replace
directive to the top module's go.mod
file, such as:
replace example.com/localModule/model v0.0.0 => ./model
which lets the top module find the other module on disk. This is covered in more detail in the replace FAQ and "Multi-module repositories" section on the Modules wiki.
However, this is a more complex solution, can be hard to get right, is usually more on-going work, and has some limitations like replace
is ignored for all modules except the current module. For most people, a multi-module repo is probably is not what they want. It is relatively rare at this point to really need to have multiple modules in a single repository.
While it is possible to use a replace
directive, the more common and straightforward solution is:
go.mod
file in your repository, and go.mod
file in the root of your repository. This is a very simple solution, and it means your two packages within the repository will be able to find each other automatically without needing any replace
, and which avoids the error message you reported.
replace
with multi-module repo, vs. single module repo?Russ Cox commented in #26664:
For all but power users, you probably want to adopt the usual convention that one repo = one module. It's important for long-term evolution of code storage options that a repo can contain multiple modules, but it's almost certainly not something you want to do by default.
If you instead want to have multiple modules defined within a single repository, there is a fair amount of nuance about how to do so properly, and there is an entire section of the Modules wiki that should be read about how to manage the complexity associated with multiple modules in a single repository, including this advice:
Adding modules, removing modules, and versioning modules with multiple modules in a single repository requires considerable care and deliberation, so it is almost always easier and simpler to manage a single-module repository rather than multiple modules in an existing repository.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With