Go List Command and x/mod Package¶
This blog try to introduce the go list
command and brief a refinement at go1.16
. Moreover, we will explore the differences between go list -m all
and go list all
, and answer question why some of the module from go list -m all
cannot be found by go mod why
.
Finally, we will see the x/mod
package and when it's useful.
Usage of 'go list'¶
The go list
is used to list all dependencies of a module, no matter direct or indirect. Because of go list
retrieves all dependencies of the current module, it requires to download the packages from the internet and the go.mod
is tidy.
For example, given the go.mod
below, we can use go list
to see the module information:
- get the module only:
-
get all used module:
-
get all direct dependencies:
Differences Between 'go list' and 'go mod why'¶
Not all modules output by go list -m all
could be found via go mod why -m
, as the go issue states as well.
$ go mod why -m nullprogram.com/x/optparse
# nullprogram.com/x/optparse
(main module does not need module nullprogram.com/x/optparse)
The module reporting is inconsistency, go list -m all
lists all modules implied by the requirements of the main module, while go mod why
focuses on the actual packages used in a build.
Because the go mod why
actually uses the go list all
to filter the result, here we actually are discussing the -m
flag of go list
.
The -m flag causes list to list modules instead of packages.
The go list -m all
includes all modules that are dependencies of the main module, even if it's not used by the main module. This is case usually happened at the module is contained by another module or it's only used in specific build constraint.
Another big difference is that the go list all
doesn't contain the version of package, because go module version is based on the module concept.
How 'go list' Got Refined Before¶
In 2018, one of user complained the side effects caused by go list
. In short, he complained:
- download the imported libraries from internet
- build CGO packages
go.mod
is modified
The first and second items here are kept now, the network is needed to run go list
because it validates the go.mod
and go.sum
. Regarding on the third item, rsc has raised a refinement proposal in 2020 during the development of go1.16 to report error rather than modifying go.mod
.
I suspect there are many more of these. In general, while the automatic additions to go.mod seemed good on paper, my impression is that they haven't delivered the vision we wanted: they do the wrong thing too often, they slow down the compile-edit-debug cycle for typos, and they are confusing.
After that, most of the go commands use default -mod=readonly
. Hence, if you modify your go.mod
without running go mod tidy
, the go list
will yield an error in go1.16
.
$ go version
go version go1.17 darwin/amd64
$ go list -m all
go: github/xieyuschen/[email protected]:
missing go.sum entry for go.mod file; to add it:
go mod download github/xieyuschen/exmaple
Module x/mod¶
The x/mod module literally provides functionalities to parse and process the go.mod
file.
It helps to parse the mod file, extract the dependencies of the projects, and manipulate them.
In practice, when we split the implementations and interfaces of code into different components, during build, we will use CLI tool to combine the implementation code, user's code(import interface) and the generated code together and then trigger the go build.
In this scenario, it's important to ensure the interfaces and implementations are compatible. As a result, we need to scan the go.mod
to validate the compatibility. At this stage, we can consider to use the x/mod
instead of go list
because go list
requires the go mod tidy
to be run first, which is time-consuming. We should report error as soon as possible.
In contrary, because it doesn't run go mod tidy
first, users might manually edit the go.mod
without go mod tidy
. This could trespass the validation but doesn't make sense, so we don't handle this case.