How I want to use Go's versioned modules

August 3, 2018

I thought that I understood Go's 'vgo' versioned modules after reading things like Russ Cox's "Go & Versioning" series. Then I started poking at them for the usage cases I'm interested in, and now I'm more confused than before.

The available Go documentation makes it pretty clear how to work with Go modules for your own code, and there are walk-throughs like Dave Cheney's Taking Go modules for a spin. But much of my use of Go is in fetching and building other people's Go programs (eg, a handy TLS certificate inspector, this handy program that I should use more often, and of course my favorite Let's Encrypt client). It's not clear how Go modules interact with this in a future world where these packages have go.mod files that specify what versions of their dependencies they should be built with, and certainly there doesn't seem to be any interaction now.

When I'm building Go programs like this, I'm acting as what I've called an infrequent developer and I basically want things to just work. If a program has a go.mod file, the most likely way to have things just work is to use the dependency version information from go.mod (it's what the program is advertising as right, after all). For usability I want this to happen automatically on plain 'go get <package>' or something very like it, because that's what I and many other people are going to use.

(I absolutely will not be manually cloning VCS repos to somewhere, cding to it, and running 'go build' just so I can have Go respect the package's go.mod. It's an extremely useful feature of Go that I can go from nothing to an installed program with a single command.)

All of this leads me to want a model of go.mod usage where Go commands respect go.mod if one is present but still work and behave traditionally if there isn't one. I want this to happen whether or not the package in question is in $GOPATH/src, partly because that means I don't have to care whether any particular program has added a go.mod yet. The Go developers don't seem to have any interest in supporting this approach, though; perhaps they consider it too unpredictable.

(I consider it very predictable; I will get whatever the authors of the module think is best. If they like go.mod, I'll automatically use that; if they vendor some or all things, I'll use that; otherwise, I'll use the Go default of 'the latest version of everything', which they're presumably fine with since they left their program that way.)

PS: Given that the latest Go tip still doesn't seem to have any way of using a package's go.mod if you just do 'go get <package>', I suspect that the Go developers consider handling this in any way to be out of scope for the first version of Go modules. These days I'm not sure they even like 'go get <package>', or if they've switched over to considering it a mistake that they're more or less locked in to supporting to some degree.

PPS: For existing packages you have fetched, you could get what I want by writing a cover script for go that manipulates $GO111MODULE based on whether or not there's a go.mod file in an appropriate spot. Having to write this cover script seems wasteful, though, since Go is already perfectly capable of checking for itself.

(At least according to the documentation, setting $GO111MODULE to on doesn't quite do this. Instead it claims to make use of go.mod mandatory, at least as I'm reading the 'go help modules' documentation. The actual behavior in my tests doesn't necessarily match this, so the whole thing leaves me confused.)

Written on 03 August 2018.
« Ubuntu 18.04's problem with Amanda's amrecover
Firefox now implements its remote control partly over D-Bus »

Page tools: View Source, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Fri Aug 3 00:58:24 2018
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.