What Is the Purpose of `go mod vendor` in Go Modules?
go mod vendor copies all of a module's build-time dependencies into a local vendor directory and generates a vendor/modules.txt manifest, enabling reproducible offline builds and compatibility with legacy GOPATH-mode tools.
When working with Go modules in the golang/go repository, the go mod vendor command serves as a materialization tool that freezes your dependency graph into the filesystem. This ensures that your project's build requirements are self-contained, allowing compilation without external network access while maintaining explicit version tracking through the generated manifest.
Core Purpose and Benefits of go mod vendor
The go mod vendor command addresses several specific needs in the Go module ecosystem:
Reproducible Offline Builds
By materializing the exact source code of every required module into the vendor directory, builds no longer depend on external proxies or network access. This ensures that the same code is compiled every time, regardless of network availability or upstream repository changes.
Compatibility with GOPATH-Mode Tools
The vendor layout intentionally mimics the GOPATH src tree structure. This allows legacy tools and workflows that expect dependencies to reside in ./vendor to locate and use the correct packages without modification.
Controlled Vendoring Scope
The command deliberately excludes non-essential artifacts. According to the implementation in src/cmd/go/internal/modcmd/vendor.go, the matchPotentialSourceFile filter removes test files (*_test.go) and, for Go versions 1.17 and later, omits go.mod and go.sum files from the vendored copy. Only files necessary for building your application are preserved.
Explicit Version Tracking
The generated vendor/modules.txt file records the selected module versions and any replace directives. This manifest allows the -mod=vendor build mode to verify consistency and reject mismatched vendoring, ensuring the build uses exactly what was intended.
How go mod vendor Works Under the Hood
The implementation in src/cmd/go/internal/modcmd/vendor.go orchestrates a multi-step process to create the vendor directory:
Loading Packages Across the Module Graph
The command begins by loading all packages using modload.LoadPackages(..., "all") with the options UseVendorAll: true and AllowErrors (when the -e flag is specified). This ensures that every transitive dependency required for building is identified, even if some packages contain errors.
Grouping by Module
After loading, the system groups packages by the module that provides them (modpkgs). This organization ensures that each module's source files are consolidated into the appropriate subdirectory within vendor/.
Filtering Source Files
Before copying, each file passes through the matchPotentialSourceFile test. This filter excludes test files and metadata files that are not required for compilation, ensuring the vendor directory contains only build-essential code.
Generating the Manifest
The command writes vendor/modules.txt using the moduleLine function to describe each vendored module, including any replacement paths specified in your go.mod. This manifest serves as the source of truth when verifying vendored dependencies during builds.
Copying Source and Metadata
Valid source files are copied into the target vendor directory via vendorPkg, while module metadata such as LICENSE and NOTICE files are preserved through copyMetadata. This ensures compliance with license requirements while maintaining a clean source tree.
Workspace Support
For multi-module workspaces, the go work vendor command (implemented in src/cmd/go/internal/workcmd/vendor.go) performs the same operation at the workspace level. Low-level helpers for reading existing vendor manifests and checking consistency reside in src/cmd/go/internal/modload/vendor.go.
Practical Usage Examples
Create a vendor directory for the current module:
go mod vendor
Build using the vendored copy without network access:
go build -mod=vendor ./...
Inspect the generated manifest:
cat vendor/modules.txt
Vendor to a custom location (useful for external tooling):
go mod vendor -o ./third_party/vendor
Continue even if some packages fail to load (e.g., missing test files):
go mod vendor -e
In a workspace, vendor all modules at once:
go work vendor
Summary
go mod vendorcreates a localvendordirectory containing all build-time dependencies and amodules.txtmanifest.- It enables reproducible offline builds by removing network dependencies during compilation.
- The command excludes test files and unnecessary metadata through the
matchPotentialSourceFilefilter. - It maintains GOPATH compatibility for legacy tooling expecting the
./vendorlayout. - The
-mod=vendorbuild flag usesvendor/modules.txtto verify consistency and ensure deterministic builds. - Workspace support via
go work vendorextends vendoring to multi-module workspaces.
Frequently Asked Questions
What is the difference between go mod vendor and go mod download?
go mod download caches module source code in the local module cache (typically $GOPATH/pkg/mod) but does not copy files into your project directory. In contrast, go mod vendor copies dependencies into a local vendor directory within your project, allowing version control of dependencies and offline builds. The vendor directory also excludes test files and generates a modules.txt manifest for verification.
Does go mod vendor include test files?
No. The matchPotentialSourceFile function in src/cmd/go/internal/modcmd/vendor.go explicitly filters out files matching *_test.go. This keeps the vendor directory focused strictly on build-time dependencies, reducing repository size and avoiding potential test-related errors in vendored code.
How do I build using vendored dependencies?
Use the -mod=vendor flag with standard build commands. For example: go build -mod=vendor ./.... This tells the Go toolchain to use the sources in the vendor directory instead of the module cache, verifying against vendor/modules.txt to ensure the vendored code matches the expected versions.
Can I customize the vendor directory location?
Yes. You can specify a custom output directory using the -o flag: go mod vendor -o ./third_party/vendor. This is particularly useful when integrating with external tooling that expects dependencies in specific locations, though the standard vendor/ directory is recommended for most projects to ensure -mod=vendor works correctly without additional configuration.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →