Golang. 替换非真正 Go 包的模块路径

huangapple go评论73阅读模式
英文:

Golang. Replace module path for package that are not real go packages

问题

这是要翻译的内容:

有这个包 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语句中应该放什么?

英文:

There is this package https://github.com/open-telemetry/opentelemetry-proto
which contains protobuf definitions only. To generate golang code one must type:

make gen-go

and go build fails with following message:

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

I've tried to replace one path with another in go.mod file but apparently I'm not too good at it. How can I make it work?

I've copied those generated files to

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

what should I put in import statement inside my main package?

答案1

得分: 5

Go源代码生成方式存在一些挑战。我猜测仓库的作者们希望在不同语言和使用GOPATHGO MODULES的情况下保持一致性,所以对他们和我们来说都有些复杂。

下面是一个解决方案:

假设你在/path/to/somedir目录下,该目录包含了opentelemetry-protomy-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-module目录下执行go 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

注意:由于他们没有使用Go Modules,所以需要使用GOPATH路径到达包的位置。如果我们使用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() {
	// 例如
	_ = v1.ExportMetricsServiceRequest{}
}

解释:

make gen-go不会创建一个Module,但我们可以手动创建一个。

Module的路径是从gen/go目录下的路径推断出来的,即github.com/open-telemetry/opentelemetry-proto

然后,我们可以在我们的项目中使用replace指令来提供一个本地路径。该路径是克隆版本的路径,然后回退到我们新创建的go.mod文件所在的位置。

导入路径是从Module开始的路径(即那个非常复杂的replace路径),指向我们感兴趣的包。

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

我的建议是:

我认为生成的代码的Module应该与其仓库匹配。如果opentelemetry-proto是我的仓库,我会将生成的源代码放在仓库根目录下,而不是gen/go目录下。

这样做会简化一切,例如:

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

以及:

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

There are a couple of challenges with the way the Go sources are generated. I assume that the repo authors are aiming for consistency across languages and for GOPATH and GO MODULES use-cases with Go.... so, yes, gnarly for them and us.

Here's a (!?) solution:

Assuming you're in /path/to/somedir and it contains a clone of the opentelemetry-proto and ``my-module` at the same level, i.e.:

.
├── my-module
└── opentelemetry-proto
  1. make gen-go as before. This should create ./opentelemetry-proto/gen

  2. In ./opentelemetry-proto/gen/go/github.com/open-telemetry/opentelemetry-proto go go mod init github.com/open-telemetry/opentelemetry-proto:

.
├── gen
└── go.mod
  1. From within my-module, go mod init my-module and then:

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

> NOTE With GOPATH paths down to packages are required (they're not using Go Modules) and so, if we were using GOPATH, we could GOPATH=${GOPATH}:${PROTO_GEN_GO_DIR}/github.com/open-telemetry/opentelemetry-proto

And then, e.g.

main.go:

package main

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

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

Explanation:

make gen-go does not create a Module but we can create one.

The Module is implicit from the path under gen/go i.e. github.com/open-telemetry/opentelemetry-proto

Then, from our project, we can replace to provide a local path to it. The path is the path to the clone, then back down to our newly-created go.mod.

The import path is the path from the Module (i.e. that excessively convoluted replace path) to whichever package we're interested in.

> NOTE Commonly protobuf imports are pb but I've used v1.

What I would do:

I think the Module of generated code should match its repo. If opentelemetry-proto were mine, I'd generate the sources into the repo root without gen/go

As this would -- IMO -- simplify everything to:

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

And:

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

huangapple
  • 本文由 发表于 2021年10月11日 00:35:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/69517065.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定