Useful walkthrough. One sharpening: pair go mod graph with go mod why <module>. The graph shows you the edges, why tells you which of your imports actually pulls a module in, which is what you need when deciding what to cut. Also worth noting for readers: since Go 1.17 module graph pruning, the graph is shallower than it used to be. And a "cycle" in require directives is a version-selection quirk. True import cycles are still rejected by the compiler.
Thanks, good points. I agree on pairing the two. The "why" section touches on this: go mod why -m follows the package import graph, and the requirement graph shows which chain of go.mod files brought a module in. When you're deciding what to cut, the import chain is the one to act on.
The pruning note is a useful addition. Since Go 1.17, the graph leaves out the deeper requirements of modules that declare go 1.17 or later, so the same project can show a much smaller graph than it did on older Go versions. Worth keeping in mind when comparing graph sizes across projects.
And yes, the cycle in the article is a requirement cycle between the otel modules, which Go allows. An import cycle between packages is a compile error, so the compiler already catches that one.
Glad it landed. And good confirmation on the otel requirement cycle. Exactly the kind that slips past you in a monorepo, since Go won't stop you from building one.
Parsa Aftabi
Backend & Full-Stack Engineer — building high-performance systems and clean APIs. Go · TypeScript · React · PostgreSQL · Redis · Docker
Useful walkthrough. One sharpening: pair go mod graph with
go mod why <module>. The graph shows you the edges, why tells you which of your imports actually pulls a module in, which is what you need when deciding what to cut. Also worth noting for readers: since Go 1.17 module graph pruning, the graph is shallower than it used to be. And a "cycle" in require directives is a version-selection quirk. True import cycles are still rejected by the compiler.