在 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.