43

我在使用 go 的新模块系统时遇到问题,因为我想定义一个本地模块并将其导入到主程序中。本地包位于主包/根文件夹的文件夹中。想象一下在$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
}

在根文件夹中,我通过调用初始化了一个模块

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

我在go1.11 darwin/amd64运行 MacOS 10.13.6 的 Macbook 上使用。

4

2 回答 2

45

您可以通过在 go.mod 中添加 require 语句和具有相对文件路径的匹配替换语句来获得所需的本地“子”模块。

在“根”./go.mod 中:

module example.com/localModule

require example.com/localModule/model v0.0.0

replace example.com/localModule/model v0.0.0 => ./model
于 2018-09-12T19:46:52.797 回答
6

根本问题

您收到此错误的原因是您定义了两个不知道如何在本地磁盘上找到彼此的模块。

$ go build
main.go:4:8: unknown import path "example.com/localModule/model": 
 cannot find module providing package example.com/localModule/model

解决方案1:replace

您可以将replace指令添加到顶部模块的go.mod文件中,例如:

replace example.com/localModule/model v0.0.0 => ./model

这让顶部模块可以找到磁盘上的另一个模块。这在模块 wiki 上的替换常见问题“多模块存储库”部分中有更详细的介绍。

然而,这是一个更复杂的解决方案,很难正确解决,通常是更多的持续工作,并且有一些限制,例如replace除了当前模块之外的所有模块都被忽略。对于大多数人来说,多模块 repo 可能不是他们想要的。在这一点上,真正需要在一个存储库中拥有多个模块的情况相对较少。

解决方案 2:一个 repo == 一个模块

虽然可以使用replace指令,但更常见和直接的解决方案是:

  • 在您的存储库中有一个go.mod文件,并且
  • 将该单个go.mod文件放在存储库的根目录中。

这是一个非常简单的解决方案,这意味着您在存储库中的两个包将能够自动找到彼此而无需任何replace,并且避免了您报告的错误消息。

replace与多模块回购相比,与单模块回购?

Russ Cox 在#26664中评论:

对于除高级用户之外的所有用户,您可能希望采用通常的约定,即一个 repo = 一个模块。repo可以包含多个模块,这对于代码存储选项的长期发展很重要,但几乎可以肯定默认情况下您不想这样做。

如果您希望在单个存储库中定义多个模块,那么关于如何正确执行此操作有相当多的细微差别,并且应该阅读模块 wiki 的整个部分,了解如何管理与单个存储库中的多个模块,包括以下建议:

在单个存储库中添加模块、删除模块和对具有多个模块的模块进行版本控制需要相当多的谨慎和深思熟虑,因此管理单个模块存储库而不是现有存储库中的多个模块几乎总是更容易和更简单。

于 2019-04-17T20:23:54.510 回答