In a Go workspace, what does `go work sync` change in each module's go.mod?
answer
- one build list, several go.mod files
- the workspace picked a higher version
- push the selection back down
- raises requirements, never adds them
- not a substitute for tidy
basics
~20 sgo work sync computes one dependency version list for the whole workspace, then writes those selected versions back into the go.mod of each module the workspace uses. It raises requirements a module already declares; it does not add new ones.
solid answer
~40 sInside a workspace the go command builds every `use`d module against one combined build list: minimal version selection runs over the union of all their requirements. So if one workspace module requires `example.com/x v1.2.0` and another requires `v1.5.0`, everything you build in that workspace compiles against `v1.5.0` — and the first module, built on its own, would still compile against `v1.2.0`. That drift is invisible until something breaks. `go work sync` closes it: it resolves the workspace build list and pushes the selected versions back into each workspace module's `go.mod`, upgrading requirements those modules already declare. It does not invent a requirement a module never had, so it is a version-alignment tool, not a replacement for running `go mod tidy` in each module.
code
mod · 7 lines// api/go.mod
require example.com/x v1.2.0
// worker/go.mod
require example.com/x v1.5.0
// after `go work sync`, api/go.mod requires example.com/x v1.5.0go deeper
Know that a workspace builds all its modules against one shared set of dependency versions, and that go work sync exists to write those versions back into the modules' go.mod files.
Explain the mechanism: minimal version selection runs over the union of the workspace modules' requirements, sync pushes the result back, and it upgrades existing requirements rather than adding new ones.
Show that you run it before releasing anything developed in a workspace, and that you can name the failure it prevents — a module tested against a higher version than its own go.mod declares.
Decide where version alignment is enforced: a sync-and-verify step in the release path, or a rule that shared dependency versions are raised in every module in the same change.
## One build list across several main modules Outside a workspace, each module resolves its own dependency versions. Minimal version selection reads the module's `require` lines plus the requirements of everything it depends on, and picks, for each dependency, the highest version anybody asked for — the *minimum* that satisfies all requirements, not the newest release. In workspace mode there is not one main module but several, and the go command runs that same selection over the union of all of them. The result — the workspace build list — is what every package in the workspace compiles against. This is what makes a workspace useful: the service and the library you are editing together see one consistent set of dependency versions, so you cannot get a build where two halves of your own code disagree about the version of a shared dependency. It also creates a gap. Consider: ``` // api/go.mod require example.com/x v1.2.0 // worker/go.mod require example.com/x v1.5.0 ``` With both in the workspace, the build list selects `v1.5.0`, and `./api` is compiled against `v1.5.0` every time you build locally. But `api`'s own `go.mod` still says `v1.2.0`. Anyone who builds `api` alone — CI, a consumer, you after deleting `go.work` — gets `v1.2.0`. If the code you just wrote uses something added in `v1.3.0`, it compiles for you and fails for them. ## What `go work sync` does `go work sync` resolves the workspace build list and then writes the selected versions back into the `go.mod` files of the workspace's modules. In the example above, `api/go.mod` ends up requiring `example.com/x v1.5.0` — the version it has actually been built and tested against all along. Two boundaries define the command: - **It upgrades, it does not add.** A requirement a module already declares is raised to the workspace-selected version. A dependency the module never mentioned is not inserted, even if the workspace build pulled it in. If `api` imports a package and has no `require` for it at all, `go work sync` leaves that hole exactly where it was. - **It works on the modules the workspace uses.** It writes to the `go.mod` files under `use`, not to anything downloaded into the module cache and not to modules outside the workspace. So the mental model is: *sync makes each module's declared requirements match what the workspace has been building.* It is the command you run before releasing a module you have been developing inside a workspace, so that its published requirements describe the versions your tests actually exercised. ## `go work sync` versus `go mod tidy` These solve different problems and neither substitutes for the other. `go mod tidy` operates on one module. It scans that module's packages for imports, adds requirements for what is imported, removes what is not, and writes `go.sum` entries to match. It resolves through the module graph — it is not workspace-aware and does not consult the `use` list — so inside a workspace it will try to resolve an import of a sibling workspace module through the proxy, which fails if that module has never been published. That is deliberate: tidy tells you the truth about the module standing alone. `go work sync` is workspace-aware by definition, but only adjusts versions of requirements that already exist. Running both, in the right situations, is normal: tidy to get each module's requirement *set* right, sync to get the *versions* aligned with the workspace. ## `go.work.sum` Alongside `go.work` the go command may write a `go.work.sum`. Each module has its own `go.sum` recording cryptographic checksums of the module versions it needs. A workspace build can need a version that no single module's `go.sum` covers — typically a dependency version selected only because another workspace module required it higher. Those extra checksums go into `go.work.sum`, next to the `go.work` file, and are verified the same way. It supplements the modules' own `go.sum` files rather than replacing them: each module still carries everything its standalone build needs. ## When you reach for it After upgrading a dependency in one workspace module and wanting the others to declare the same version. Before tagging or releasing any module developed in a workspace, since consumers read that module's `go.mod`, not your build list. And when a module built alone behaves differently from the same module built in the workspace — the version gap sync exists to close is the first thing to check.
- What is stored in go.work.sum, and why is it separate from each module's go.sum?It sits next to `go.work` and holds checksums for module versions the workspace build needs but that no individual module's `go.sum` covers — usually a version selected only because another workspace module required it higher. Each module keeps its own `go.sum` complete for its standalone build, so `go.work.sum` supplements rather than replaces them.
- Does `go mod tidy` in one workspace module see the other workspace modules?No. `go mod tidy` operates on a single module and resolves imports through the module graph, not through `go.work`'s use list. Inside a workspace it will therefore try to fetch a sibling module from the proxy and fail if that module was never published. That is intentional: tidy reports what the module needs standing alone.
- When would you run `go work sync` in practice?After raising a dependency in one workspace module so the others declare the same version, and before tagging or releasing any module you have been developing in the workspace. Consumers resolve through the module's own `go.mod`, so its requirements should name the versions your workspace builds and tests actually used.
saying these in an interview costs you the question
- Says go work sync adds missing require lines
- Thinks each workspace module builds against its own versions
- Believes go work sync and go mod tidy are the same
- Assumes go.work.sum replaces each module's go.sum
- Claims minimal version selection picks the newest release