walking through the rsc.io/quote example

This post: https://research.swtch.com/vgo-tour

setting up and looking around

import the package by plopping import "rsc.io/quote" into a source file. (and using it because for some reason unused imports are a hard error. just go things tm)

package main

import "fmt"
import "rsc.io/quote"

func main() {
    fmt.Println(quote.Hello())
}

go commands auto-download missing dependencies (?!), so go run . already works and can print quotes.

Another way to kick the tires is go mod tidy, which ensures go.mod is up-to-date wrt the list of packages mentioned in the source code. (and re-formats the file.)

What versions of packages do you get? this picks:

In practice this means that when you install X and the latest version is v2, the transitive dependencies you get are the versions that the author of X had in their dependency file. (Kinda like when i use gradle.)

now go.mod looks like this:

module go.highlysuspect.agency/hello

go 1.25.6

require rsc.io/quote v1.5.2

require (
    golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
    rsc.io/sampler v1.3.0 // indirect
)

Let’s check go mod graph

$ go mod graph
go.highlysuspect.agency/hello go@1.25.6
go.highlysuspect.agency/hello golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c
go.highlysuspect.agency/hello rsc.io/quote@v1.5.2
go.highlysuspect.agency/hello rsc.io/sampler@v1.3.0
go@1.25.6 toolchain@go1.25.6
rsc.io/quote@v1.5.2 rsc.io/sampler@v1.3.0
rsc.io/sampler@v1.3.0 golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c

this tracks with the source code (quote, sampler)

checking for updates

The magic word is go list -m -u all.

$ go list -m -u all
go.highlysuspect.agency/hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c [v0.33.0]
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0 [v1.99.99]

Can I complain about this CLI?

anyway. It looks like there’s a new version of x/text and sampler. Upgrading x/text:

$ go get golang.org/x/text@v0.33.0
go: upgraded golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c => v0.33.0

checking go.mod reports the indirect dependency has been upgraded from the random commit version to v0.33.0. Nice.

something about go test

There’s a part in the blogpost about go test that I don’t understand the modern version of:

In the original go command, the package pattern all meant all packages found in GOPATH. That’s almost always too many to be useful. In vgo, we’ve narrowed the meaning of all to be “all packages in the current module, and the packages they import, recursively.”

But go test all started testing all packages on the system including Go internal packages, and go test -m all tested only my package (which doesn’t have any tests). I’m not sure how to test only my dependencies (or, tbh, if i’d even want to)

upgrading sampler

This is the part where you go get -u rsc.io/sampler and discover it has a bug, prints the wrong message instead of hello.

downgrading sampler

Listing versions for a package can be done with go list -m -versions (package)

$ go list -m -versions rsc.io/sampler
rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99

-v does not work, gotta spell it out.

Then pin the package to the version you want:

$ go get rsc.io/sampler@v1.3.1
go: downgraded rsc.io/sampler v1.99.99 => v1.3.1

And it can be marked as something we don’t want by adding exclude rsc.io/sampler v1.99.99 to go.mod. Note that adding an exclusion is really strong and other commands act like the version doesn’t even exist. It’s even gone from go list -m -versions.

$ go list -m -versions rsc.io/sampler
rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1

And exclusions are nontransitive. Downstream consumers can still end up resolving to a version you tried to exclude. Hmm, this seems like a bad idea but what do I know.

vendoring quote

Works for me.

vendoring everything

go mod vendor plonks the following into vendor/modules.txt

# golang.org/x/text v0.33.0
## explicit; go 1.24.0
golang.org/x/text/internal/language
golang.org/x/text/internal/language/compact
golang.org/x/text/internal/tag
golang.org/x/text/language
# rsc.io/quote v1.5.2 => ./quote
## explicit
rsc.io/quote
# rsc.io/sampler v1.3.1
## explicit
rsc.io/sampler

and copies of the relevant libraries are all under vendor.

This is kind of a node_modules situation.

changes since the original rsc post about go modules

go.mod now includes information about the version of Go used. That didn’t exist at first.

Transitive dependencies are now added to go.mod with an //indirect comment. Apparently this was changed for “lazy loading” purposes but in practice, it means all those “minimal version selection is reproducible, so there’s no need to list the transitive closure of your dependencies!” notes didn’t shake out. frankly I think it’s kind of a good change because seeing the entire dependency graph is good for your health :)

Apparently you can also get //indirect comments if you dep on pre-modules Go code. This seems wrong though…? (it looks like what actually changed in OP’s question is that Go was dumping all the dependencies into one list, now it sorts direct deps before indirect ones, so it’s easier to spot the module op actually wanted)

other ways to upgrade packages

go get -u: upgrade EVERYTHING

go get (package): upgrade that package (and its transitive dependencies) to the latest version

You don’t need -u. go get -u (package) does the same thing(?).

Seems typosquattable!!! dont fuck up that URL!!!

questions

it seems the other major versions are under rsc.io/quote/v4?

also this: https://go.dev/ref/mod#incompatible-versions

some background is in this article.

hm