[已解决] 在现有项目中使用Go模块时遇到的错误

[已解决] 在现有项目中使用Go模块时遇到的错误 我在一个已存在的项目中开始使用Go模块。运行了 go mod initgo mod tidy 后,我遇到了以下问题:

go mod tidy
go: downloading github.com/ghodss/yaml v1.0.0
go: extracting github.com/ghodss/yaml v1.0.0
go.etcd.io/etcd/discoveryserver/handlers imports
go.etcd.io/etcd/etcdserver/api/v2store: module go.etcd.io/etcd@latest (v3.3.17+incompatible) found, but does not contain package go.etcd.io/etcd/etcdserver/api/v2store

我不知道如何解决 module go.etcd.io/etcd@latest (v3.3.17+incompatible) found, but does not contain package go.etcd.io/etcd/etcdserver/api/v2store 这个问题。非常感谢任何帮助。


14 回复

你能发布一下 go.mod 的内容吗?我需要在这里本地尝试一下。


非常感谢 @hollowaykeanho

这是我的荣幸。😄 欢迎随时在另一个主题中再次提问。

我已经能够让服务器运行了。我认为接下来要做的是修复 Go 模块与发布版本之间的兼容性问题。我将把这个问题标记为已解决,非常感谢 @hollowaykeanho

看起来 v2store 不存在。我浏览了模块文件夹,确实没有。我正在查看其他版本,看看它们是否包含 go.etcd.io/etcd/etcdserver/api/v2store 包。 $ echo $GO111MODULE -> 空

我将尝试 v3.4.2 版本,但是代码中导入的版本并非来自 GitHub:

import ( .... "go.etcd.io/etcd/etcdserver/api/v2store" .... )

etua:

代码中导入的版本并非来自 GitHub: import ( .... "go.etcd.io/etcd/etcdserver/api/v2store" .... )

别担心。你可以先尝试使用镜像域名 go.etcd.io,如果不行再试试 github.com

按理说,它应该能正常工作。

几个探索性问题,按顺序来:

  1. 你的 GO111MODULE 是什么?(命令:go env GO111MODULE

  2. 在任意 Go 模块包目录之外,尝试执行 export GO111MODULE=on && go get -u github.com/etcd-io/etcd@v3.3.17。在本地能成功吗?

我无法在此复现这个错误,因此需要你在你那边协助排查。到目前为止,我能够毫无问题地 go get 这个包。

我使用了提交哈希,现在 go.mod 文件的内容是:

go.etcd.io/etcd v0.5.0-alpha.5.0.20191009222652-bbe86b066c0c

这应该是 v3.4.2 才对,对吗?另外,你能告诉我哪里可以读到关于这个的内容吗: 正如 go1.13.X 所预期的那样。它对 v1、v2…… 目录方法的要求变得严格了。

etua:

无效版本:模块包含一个 go.mod 文件,因此主版本必须兼容:应为 v0 或 v1,而不是 v3

哦,是的。正如在 go1.13.X 中预期的那样。它对 v1v2…… 这种目录方法的要求变得严格了。目前,该项目并未采用那种目录方法。

你能尝试将 v3.4.2 替换为它的提交 ID:bbe86b066c0c714fa2a17ee93a37882553cf2394 吗?他们只维护单一的 master 分支(master 分支始终处于前沿),因此在这种情况下使用 @master 是不安全的。

这是 go.mod 的内容:

module go.etcd.io/etcd/discoveryserver

go 1.13

require (
	github.com/coreos/etcd v3.3.17+incompatible // indirect
	github.com/google/uuid v1.1.1 // indirect
	github.com/gorilla/handlers v1.4.2
	github.com/gorilla/mux v1.7.3
	github.com/prometheus/client_golang v1.2.1
	github.com/spf13/pflag v1.0.5
	github.com/spf13/viper v1.4.0
	go.etcd.io/etcd v3.3.17+incompatible
	google.golang.org/grpc v1.24.0
	sigs.k8s.io/yaml v1.1.0 // indirect
)

$ echo $GO111MODULE -> 空

你正处于自动模式。我刚刚交叉核对了它们的发布版本:

v3.3.17 版本没有 v2store

//github.com/etcd-io/etcd/tree/v3.3.17/etcdserver/api

然而,v.3.4.2 版本确实有 v2store。升级到 v3.4.2 可以吗?

//github.com/etcd-io/etcd/tree/v3.4.2/etcdserver/api

这是我尝试使用 v3.4.2 版本时得到的结果:

verifying go.etcd.io/etcd@v3.4.2+incompatible/go.mod: go.etcd.io/etcd@v3.4.2+incompatible/go.mod: reading https://sum.golang.org/lookup/go.etcd.io/etcd@v3.4.2+incompatible: 410 Gone

这是通过直接修改 go.mod 文件完成的。 使用 go get 命令:

go get -u go.etcd.io/etcd@v3.4.2
go: finding go.etcd.io/etcd v3.4.2
go get go.etcd.io/etcd@v3.4.2: go.etcd.io/etcd@v3.4.2: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v3

etua:

我使用了提交哈希,现在 go.mod 文件显示为:

预期会出现伪版本。除非项目遵循主版本号大于或等于 2 的标签所对应的版本目录方法,否则无法使用标签版本。

etua:

你能告诉我可以在哪里阅读到关于这个的内容吗: 正如在 go1.13.X 中所预期的那样。它对于 v1, v2, … 目录方法变得更加严格。

当然可以。

实际文档:

  1. Modules · golang/go Wiki · GitHub
  2. Go 1.13 Release Notes - The Go Programming Language (在理解了 Go 模块的内部机制之后)

问答:

  1. git - How to point Go module dependency in go.mod to a latest commit in a repo? - Stack Overflow
  2. go modules - What does ‘incompatible’ in go.mod mean, will it cause harm? - Stack Overflow (atline 解释得相当好)

类似案例:

  1. go.mod missing /v11 at the end of the module directive · Issue #1355 · kataras/iris · GitHub
  2. [POLL] Iris + Go Modules (Import path suffix or not) · Issue #1370 · kataras/iris · GitHub

一些与 vX 目录相关的示例:

  1. https://github.com/gizak/termui (注意 v3)

补充说明:如果问题已解决,请记得将其标记为“已解决”,以便其他人可以处理其他问题。=)

这个错误是因为 go.etcd.io/etcd 在 v3.3.17 版本使用了旧版导入路径,而 Go 模块期望的是新版模块路径。etcd v3 模块的包路径在模块化后发生了变化。

需要替换导入路径或使用正确的模块版本。以下是解决方案:

方案1:使用 etcd 的 v3.5+ 版本(推荐)

# 更新 go.mod 中的 etcd 版本
go get go.etcd.io/etcd/v3@latest

然后修改代码中的导入路径:

// 将原来的导入
import "go.etcd.io/etcd/etcdserver/api/v2store"

// 改为
import "go.etcd.io/etcd/server/v3/etcdserver/api/v2store"

方案2:如果必须使用 v3.3.17,使用 replace 指令go.mod 中添加:

module your-module-name

go 1.16

require (
    go.etcd.io/etcd v3.3.17+incompatible
)

replace (
    go.etcd.io/etcd => go.etcd.io/etcd v0.0.0-20210226220824-aa7126864d82
)

然后运行:

go mod tidy

方案3:使用兼容性导入 如果代码中使用了 go.etcd.io/etcd/etcdserver/api/v2store,可以尝试:

import (
    v2store "go.etcd.io/etcd/server/v3/etcdserver/api/v2store"
)

执行步骤:

  1. 备份当前的 go.modgo.sum
  2. 清理模块缓存:go clean -modcache
  3. 应用上述任一方案
  4. 运行 go mod tidy 验证

检查 etcd 版本:

go list -m all | grep etcd

如果项目中有多个 etcd 相关依赖,可能需要统一版本:

go mod edit -replace go.etcd.io/etcd=go.etcd.io/etcd/v3@v3.5.0
回到顶部