在 repo 中使用多个模块时,Go get 找不到本地包
Go get cannot find local packages when using multiple modules in a repo
我在使用 go 的新模块系统时遇到问题,因为我想定义一个本地模块并将其导入到主程序中。本地包位于主 package/root 文件夹的一个文件夹中。想象一下 $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.去
package model
type Person struct {
name string
age int
}
在根文件夹中,我通过调用
初始化了一个模块
go mod init example.com/localModule
在 model/
文件夹中,我通过调用
初始化子模块
go mod init example.com/localModule/model
错误
在根文件夹中调用以下命令失败。
$ 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
go get的错误信息被截断了,我没有解析错
我不打算将模块推送到服务器,只是需要一种引用本地包的方式 model
,所以我分别选择了 example.com/localModule/
和 example.com/localModule/model
。
我在 Macbook 运行 MacOS 10.13.6.
上使用 go1.11 darwin/amd64
您可以通过在 go.mod.
中添加 require 语句和具有相对文件路径的匹配替换语句来获得您所要求的本地 "sub" 模块
在"root"./go.mod:
module example.com/localModule
require example.com/localModule/model v0.0.0
replace example.com/localModule/model v0.0.0 => ./model
根问题
您收到此错误的原因是您定义了两个不知道如何在本地磁盘上找到彼此的模块。
$ go build
main.go:4:8: unknown import path "example.com/localModule/model":
cannot find module providing package example.com/localModule/model
解决方案 1:replace
你可以在顶层模块的go.mod
文件中添加一个replace
指令,例如:
replace example.com/localModule/model v0.0.0 => ./model
让顶层模块在磁盘上找到另一个模块。模块 wiki 上的 replace FAQ and "Multi-module repositories" 部分对此进行了更详细的介绍。
然而,这是一个更复杂的解决方案,可能很难得到正确的解决方案,通常是更持续的工作,并且有一些限制,例如 replace
除了当前模块之外的所有模块都会被忽略。对于大多数人来说,多模块 repo 可能不是他们想要的。在这一点上,真正需要在单个存储库中拥有多个模块的情况相对较少。
解决方案 2:一个 repo == 一个模块
虽然可以使用 replace
指令,但更常见和直接的解决方案是:
- 在您的存储库中有一个
go.mod
文件,并且
- 将单个
go.mod
文件放在存储库的根目录中。
这是一个非常简单的解决方案,这意味着您在存储库中的两个包将能够自动找到彼此而不需要任何 replace
,这避免了您报告的错误消息。
replace
多模块回购与单模块回购?
Russ Cox 在 #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.
如果您希望在单个存储库中定义多个模块,则关于如何正确执行此操作有很多细微差别,并且应该阅读 entire section 模块 wiki关于如何在单个存储库中管理与多个模块相关的复杂性,包括以下建议:
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.
我在使用 go 的新模块系统时遇到问题,因为我想定义一个本地模块并将其导入到主程序中。本地包位于主 package/root 文件夹的一个文件夹中。想象一下 $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.去
package model
type Person struct {
name string
age int
}
在根文件夹中,我通过调用
初始化了一个模块go mod init example.com/localModule
在 model/
文件夹中,我通过调用
go mod init example.com/localModule/model
错误
在根文件夹中调用以下命令失败。
$ 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
go get的错误信息被截断了,我没有解析错
我不打算将模块推送到服务器,只是需要一种引用本地包的方式 model
,所以我分别选择了 example.com/localModule/
和 example.com/localModule/model
。
我在 Macbook 运行 MacOS 10.13.6.
上使用go1.11 darwin/amd64
您可以通过在 go.mod.
中添加 require 语句和具有相对文件路径的匹配替换语句来获得您所要求的本地 "sub" 模块在"root"./go.mod:
module example.com/localModule
require example.com/localModule/model v0.0.0
replace example.com/localModule/model v0.0.0 => ./model
根问题
您收到此错误的原因是您定义了两个不知道如何在本地磁盘上找到彼此的模块。
$ go build
main.go:4:8: unknown import path "example.com/localModule/model":
cannot find module providing package example.com/localModule/model
解决方案 1:replace
你可以在顶层模块的go.mod
文件中添加一个replace
指令,例如:
replace example.com/localModule/model v0.0.0 => ./model
让顶层模块在磁盘上找到另一个模块。模块 wiki 上的 replace FAQ and "Multi-module repositories" 部分对此进行了更详细的介绍。
然而,这是一个更复杂的解决方案,可能很难得到正确的解决方案,通常是更持续的工作,并且有一些限制,例如 replace
除了当前模块之外的所有模块都会被忽略。对于大多数人来说,多模块 repo 可能不是他们想要的。在这一点上,真正需要在单个存储库中拥有多个模块的情况相对较少。
解决方案 2:一个 repo == 一个模块
虽然可以使用 replace
指令,但更常见和直接的解决方案是:
- 在您的存储库中有一个
go.mod
文件,并且 - 将单个
go.mod
文件放在存储库的根目录中。
这是一个非常简单的解决方案,这意味着您在存储库中的两个包将能够自动找到彼此而不需要任何 replace
,这避免了您报告的错误消息。
replace
多模块回购与单模块回购?
Russ Cox 在 #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.
如果您希望在单个存储库中定义多个模块,则关于如何正确执行此操作有很多细微差别,并且应该阅读 entire section 模块 wiki关于如何在单个存储库中管理与多个模块相关的复杂性,包括以下建议:
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.