How does vendoring work in module mode, and when is it still worth using?
go mod vendor copies the packages needed to build and test the main module into vendor/ and writes vendor/modules.txt. Since Go 1.14, if vendor/ exists and go.mod says go 1.14 or later, the go command defaults to -mod=vendor. It then builds only from vendor and checks that modules.txt is consistent with go.mod.
go mod vendor
go build ./... # uses vendor/ automatically
go build -mod=mod ./... # ignore vendor, use module cache
go work vendor # Go 1.22+: vendor for a whole workspace
When it is worth it: hermetic or air-gapped builds (Bazel, corporate CI with no network), auditing third-party code in code review, and protection against upstream repos disappearing (a proxy also helps with that).
Downsides: large diffs, and it is easy to forget re-vendoring after go get (you get an "inconsistent vendoring" error). Only packages are copied, not whole modules, so non-Go files outside those packages are missing. Test files of dependencies are not vendored either. Most teams now use a module proxy (Athens, Artifactory) plus go.sum instead.
More on Modules, Packages & Tooling
- Q413What is a pseudo-version, and when does the go command generate one?
- Q414What problem do Go workspaces (go.work) solve? How do they differ from replace?
- Q416How do internal packages work? Give an example of an allowed and a forbidden import.
- Q417Your CI can't fetch a private module from github.com/acme/secret. Walk through GOPROXY, GOPRIVATE, GONOPROXY, GONOSUMDB and GOINSECURE.
- Q418How does the Go checksum database protect the supply chain? What does go mod verify actually check?
- Q419What do the go and toolchain directives mean since Go 1.21, and how does GOTOOLCHAIN behave?