【问题标题】:Golang. Replace module path for package that are not real go packages戈朗。替换不是真正的 go 包的包的模块路径
【发布时间】:2021-11-29 15:57:19
【问题描述】:

有这个包https://github.com/open-telemetry/opentelemetry-proto 其中仅包含 protobuf 定义。要生成 golang 代码,必须键入:

make gen-go

go build 失败并显示以下消息:

build opentel: cannot load github.com/open-telemetry/opentelemetry-proto/gen/go/common/v1: module github.com/open-telemetry/opentelemetry-proto@latest found (v0.11.0), but does not contain package github.com/open-telemetry/opentelemetry-proto/gen/go/common/v

我试图在 go.mod 文件中用另一个路径替换一个路径,但显然我不太擅长。我怎样才能让它发挥作用?

我已将这些生成的文件复制到

$GOPATH/src/opentelemetry-proto/gen/go

我应该在主包中的 import 语句中添加什么?

【问题讨论】:

  • 我克隆了 repo,并从内部运行 make gen-go 并生成了一个 ./gen 目录而没有错误。 Make 过程使用docker run 运行 protoc,因此您应该(!?)不会收到错误。您是否试图以不同的方式从 protos 生成源代码?
  • 啊,你已经更新了问题;-)
  • @DazWilkin 是的 :),问题是。如何将本地包导入我的主程序。如果我删除 go.mod 和 go.sum 它可以工作,但是我不能导入其他包。这是一场噩梦。
  • 这有点乱,他们是怎么做的,不是我会怎么做的……会添加一个答案

标签: go protocol-buffers open-telemetry


【解决方案1】:

Go 源代码的生成方式存在一些挑战。我假设 repo 作者的目标是跨语言和 GOPATHGO MODULES Go 用例的一致性......所以,是的,对他们和我们来说都是粗糙的。​​

这是一个(!?)解决方案:

假设您在 /path/to/somedir 中,并且它包含同一级别的 opentelemetry-proto 和 ``my-module` 的克隆,即:

.
├── my-module
└── opentelemetry-proto
  1. make gen-go 和以前一样。这应该创建./opentelemetry-proto/gen

  2. ./opentelemetry-proto/gen/go/github.com/open-telemetry/opentelemetry-proto 转到go mod init github.com/open-telemetry/opentelemetry-proto

.
├── gen
└── go.mod
  1. my-modulego mod init my-module 内部,然后:

go.mod:

module my-module

go 1.17

require (
    github.com/open-telemetry/opentelemetry-proto v0.11.0
)

replace (
    github.com/open-telemetry/opentelemetry-proto => ../opentelemetry-proto/gen/go/github.com/open-telemetry/opentelemetry-proto

注意使用GOPATH 到包的路径是必需的(它们不使用 Go 模块),因此,如果我们使用GOPATH,我们可以GOPATH=${GOPATH}:${PROTO_GEN_GO_DIR}/github.com/open-telemetry/opentelemetry-proto

然后,例如

main.go:

package main

import (
    v1 "github.com/open-telemetry/opentelemetry-proto/gen/go/collector/metrics/v1"
)

func main() {
    // E.g.
    _ = v1.ExportMetricsServiceRequest{}
}

解释:

make gen-go 不创建模块,但我们可以创建一个。

模块隐含在gen/go 下的路径中,即github.com/open-telemetry/opentelemetry-proto

然后,在我们的项目中,我们可以通过replace 为其提供本地路径。路径是克隆的路径,然后返回到我们新创建的go.mod

导入路径是模块到我们感兴趣的任何包的路径(即过度复杂的替换路径)。

注意通常 protobuf 导入是 pb,但我使用的是 v1

我会做什么:

我认为生成代码的模块应该与其 repo 匹配。如果opentelemetry-proto 是我的,我会在没有gen/go 的情况下将源代码生成到repo 根目录中

这样——IMO——将一切简化为:

github.com/open-telemetry/opentelemetry-proto => ../opentelemetry-proto

还有:

import (
    v1 "github.com/open-telemetry/opentelemetry-proto/collector/metrics/v1"
)

【讨论】:

  • 当然可以,但我不是 Go 依赖系统方面的专家,所以我不得不问。 :) 为什么go mod init github.com/open-telemetry/opentelemetry-proto./opentelemetry-proto/gen/go/github.com/open-telemetry/opentelemetry-proto 内而不是任何其他文件夹?或者,只要其他东西“匹配”,这并不重要?比赛我的意思是这个,例如? replace ( github.com/open-telemetry/opentelemetry-proto => ../opentelemetry-proto/gen/go/github.com/open-telemetry/opentelemetry-proto
  • 可以省略将go.mod 放在生成的代码树中,但它对我有用的唯一方法是使用一个。 go.mod 定义了一个模块(并引用了模块)。模块是包的聚合。 Module 根目录位于./opentelemetry-proto/gen/go/github.com/open-telemetry/opentelemetry-proto,因为这是生成的 Golang 源代码的根目录所在的位置。如果这是我的仓库,我会配置 protoc 以将源生成到仓库根目录 (github.com/open-telemetry/opentelemetry-proto` 以避免这种冗余。
  • 我认为包作者需要考虑 Golang GOPATH 的使用以及非 Golang 的使用,因此他们选择了这个解决方案。
  • 感谢您的所有帮助,我非常感谢。顺便说一句,你有没有一些好的教程链接,我在哪里可以真正了解这个 Go 依赖系统,因为如你所见,我并不擅长它(虽然我是一个很好的 Go 编码器;))
  • 不客气。以下是有用的。我主要是从反复试验中学到的:go.dev/blog/using-go-modulesgolang.org/ref/mod
猜你喜欢
  • 2021-12-05
  • 1970-01-01
  • 2014-07-13
  • 2012-03-07
  • 2022-01-16
  • 1970-01-01
  • 2019-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多