Description
What version of Go are you using (go version
)?
$ go version go version go1.12 darwin/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GOARCH="amd64" GOBIN="" GOCACHE="/Users/dmitshur/Library/Caches/go-build" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GOOS="darwin" GOPATH="/Users/dmitshur/go" GOPROXY="" GORACE="" GOROOT="/usr/local/go" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64" GCCGO="gccgo" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/3m/rg2zm24d1jg40wb48wr0hdjw00jwcj/T/go-build766457690=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
Run the following commands in one module that has no module requirements:
$ cat go.mod
module m1
$ go mod tidy
$ cat go.mod
module m1
go 1.12
Now run the same commands in another module that has 1 or more module requirements:
$ cat go.mod
module m2
require rsc.io/quote v1.0.0
$ go mod tidy
$ cat go.mod
module m2
require rsc.io/quote v1.0.0
Additionally, if the source code in module m2 is modified to no longer import anything from the rsc.io/quote
module, and go mod tidy
is run, the first time it removes the require rsc.io/quote v1.0.0
line, leaving just module m2
. The second time it adds a go
directive.
What did you expect to see?
For modules that already exist, and do not already contain a go
directive in their go.mod file, the go
directive should either be always added automatically (i.e., during any of go build
, go test
, go mod tidy
, etc., operations), or it should never be added.
What did you see instead?
Sometimes it's added, sometimes it isn't added.
Based on investigating the code with @julieqiu and @heschik, we've found that the go
directive is always added to go.mod on any go build
, go test
, go mod tidy
, etc., operation whenever the go.mod file has exactly one statement: the module statement. If the go.mod file has at least 1 require, or replace, or exclude directive, in addition to the module statement, then various go
operations do not add a go
directive.
This behavior is surprising and hard to predict (without looking into the source code to figure it out). I suspect it's an unintentional behavior. The commit message of CL 147281 that implemented this behavior says:
cmd/go: add go statement when initializing go.mod
When creating a go.mod file, add a go statement mentioning the current Go version.
Based on that, I suspect the originally intended behavior was to make it so that a go
directive is automatically inserted only when creating a new Go module (via go mod init
), but not when working with an existing module that has a go.mod file. I will assign this to @ianlancetaylor to confirm if this is a bug, and perhaps make the decision on how and whether this issue should be resolved.
I think we should fix this and even consider backporting to Go 1.12.1. Doing so should would make the logic of when a go
directive is added easier to predict and understand, improving the user experience when in module mode.