go-systemd: Troubles with Go modules and version mismatches

I was just converting a project to a Go module, and was pleased to see #307 merged and v22.0.0 tagged. So I was trying to rely on the go-systemd module, but ran into an error:

github.com/coreos/go-systemd/journal: no matching versions for query "latest"

I can trigger this error with this simple program:

package main
import _ "github.com/coreos/go-systemd/journal"
func main() {}

I can fix it by changing the import to github.com/coreos/go-systemd/v22/journal; however, that doesn’t help when I try to import, say, etcd, which gives me this error:

$  go mod tidy
go: finding golang.org/x/net latest
go: finding github.com/coreos/pkg latest
go: finding github.com/tmc/grpc-websocket-proxy latest
go: finding golang.org/x/time latest
go: finding github.com/xiang90/probing latest
go: finding github.com/golang/groupcache latest
go: finding github.com/coreos/go-systemd/journal latest
go: finding github.com/coreos/go-systemd latest
example.com/try imports
	go.etcd.io/etcd/embed imports
	github.com/coreos/pkg/capnslog imports
	github.com/coreos/go-systemd/journal: no matching versions for query "latest"

I guess this can be fixed by capnslog adding v22 to its import, but I don’t think that package has been modularized, yet. Is there some other way I can get go mod and friends to find v22 as the latest?

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 5
  • Comments: 15 (5 by maintainers)

Commits related to this issue

Most upvoted comments

I Add this in my go.mod

replace (
  github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 latest
)

then go mod tidy, and I made it.

It will become

require (
 github.com/coreos/go-systemd v0.0.0-00010101000000-000000000000 // indirect
)

@dalu please note that your comment tone is overly aggressive, and your reply doesn’t bring any new/relevant content to this ticket. EDIT: it looks like the user got banned from GitHub and their comment removed as a whole. For anybody, in order to reduce the amount of noise here, I’ll dismiss any further similar ones in the future (as this is not a discussion forum).

Anyway, just to cover the technical side once more:

  • This repository has been tagged on a regular basis since years, way before gomod came and forced semver tags. Tags up to v21 exist but gomod does not accept them. Thus the jump to v22.0.0.
  • The (multiple) breaking changes at v22.0.0 are documented in the changelog. See https://github.com/coreos/go-systemd/pull/307 for more in-depth analysis.
  • Other repositories like github.com/mongodb/mongo-go-driver do not (yet) feel the pain of versioned import because they are at major version <= 1.
  • If you have doubts on how gomod-style imports work, please consult the Golang official documentation. A relevant excerpt has been already quoted here in https://github.com/coreos/go-systemd/issues/321#issuecomment-566004138.

For casual readers landing here, Go modules require semver-imports as explained in the official docs: https://github.com/golang/go/wiki/Modules#semantic-import-versioning.

This means that the proper way to consume this library is via versioned imports as shown in the original bug-report here and in examples: https://github.com/coreos/go-systemd/blob/2d78030078ef61b3cae27f42ad6d0e46db51b339/examples/activation/activation.go#L24

That also means that, in the future, updating to new API-breaking releases will require updating all import paths (e.g. from github.com/coreos/go-systemd/v22/foo to github.com/coreos/go-systemd/v23/foo, once v23 is released).

As an unfortunate side-effect of Go module design, mixing imports from modular and non-modular versions results in some pain (as shown above) and requires some hacks via replace. This is hopefully just a transient mess which will self-resolve as soon as all consumers migrate to Go modules.

So. How to use the latest untag version

I Add this in my go.mod

replace (
  github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 latest
)

then go mod tidy, and I made it.

It will become

require (
 github.com/coreos/go-systemd v0.0.0-00010101000000-000000000000 // indirect
)

Just for memo. If someone want use latest untag version. You can change to

replace github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 v22.1.1-0.20201123092900-87511f396ae9

😂

Yes, but note that I demonstrated the issue with no dependencies, using nothing more than

package main
import _ "github.com/coreos/go-systemd/journal"
func main() {}

I think the solution is to either:

  1. Explicitly import the version you want: import github.com/coreos/go-systemd/v22/journal. This will get the proper line in go.mod:

     require github.com/coreos/go-systemd/v22 v22.0.0
    
  2. Or use replace even if you have no other dependencies, so you replace all instances of the non-version-qualified require statement with the versioned one:

     replace github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 v22.0.0
    

    Unfortunately that means the require line won’t have the v22 requirement, oddly:

     require github.com/coreos/go-systemd v0.0.0-00010101000000-000000000000
    

Not sure why that is.

@theory to the best of my understanding, the “versionless replace” hack should work as long as the versioned and non-versioned releases of this library have no API-breaking changes.