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

Time:10-12

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?

CodePudding user response:

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"
)
  • Related