There is a circular dependency between runtime/race and cmd/cgo in -race build.
Everything depends on runtime/race, but runtime/race is a cgo package.
Currently it's resolved by a hack in go tool:
// If we are not doing a cross-build, then record the binary we'll
// generate for cgo as a dependency of the build of any package
// using cgo, to make sure we do not overwrite the binary while
// a package is using it. If this is a cross-build, then the cgo we
// are writing is not the cgo we need to use.
if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace {
We pretend that packages do not depend on cmd/cgo. But as the result we can overwrite
cmd/cgo binary while it is used.
A better solution is to make runtime/race to be not dependent on cmd/cgo.
There is a circular dependency between runtime/race and cmd/cgo in -race build. Everything depends on runtime/race, but runtime/race is a cgo package. Currently it's resolved by a hack in go tool: // If we are not doing a cross-build, then record the binary we'll // generate for cgo as a dependency of the build of any package // using cgo, to make sure we do not overwrite the binary while // a package is using it. If this is a cross-build, then the cgo we // are writing is not the cgo we need to use. if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace { We pretend that packages do not depend on cmd/cgo. But as the result we can overwrite cmd/cgo binary while it is used. A better solution is to make runtime/race to be not dependent on cmd/cgo.