When would you use a replace directive, and why doesn't a dependency's replace affect your build?
Question 411MediumGo 1.22 to 1.25
replace swaps the content of a module version for another version, another module path (a fork), or a local directory. Typical uses: testing a local fix before it goes upstream, pinning a fork, or working around a broken release.
replace (
github.com/foo/bar => ../bar // local dir (needs its own go.mod)
github.com/foo/baz v1.4.0 => github.com/me/baz v1.4.1-fix
)
Key rule: replace and exclude apply only in the main module's go.mod (and in go.work). They are ignored in dependencies. Otherwise a library could silently redirect your supply chain, and two libraries with conflicting replaces could never be combined.
Gotchas:
- A local-path replace committed to a library breaks the build for anyone without that directory. Use
go.workfor local multi-module development. go install mod@versionfails if the target module's go.mod contains replace directives. This is intentional so that the build is the same everywhere.- A replacement by path does not change import paths. Your code still imports the original path.
More on Modules, Packages & Tooling
- Q409What is semantic import versioning, and why must v2+ modules change their import path?
- Q410How do you release v2 of a module? Compare the "major branch" and "major subdirectory" strategies, and explain +incompatible.
- Q412Explain exclude and retract. Who writes each one, and how do they affect version selection?
- 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?
- Q415How does vendoring work in module mode, and when is it still worth using?