go version)?$ go version go version go1.13.10 linux/amd64
Yes
go env)?go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/karl/.cache/go-build"
GOENV="/home/karl/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/karl/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/karl/tmp/floattest/go.mod"
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 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build659173498=/tmp/go-build -gno-record-gcc-switches"
go.mod:
module floattest
go 1.11
main.go:
package floattest
func returnFloat(v float64) float64 {
return v
}
main_1_13_test.go:
// +build go1.13
package floattest
import (
"testing"
)
func TestStuff(t *testing.T) {
expected := 0x1.5fp20
actual := returnFloat(expected)
if actual != expected {
t.Errorf("Expected %v but got %v\n", expected, actual)
}
}
command: go test
ok floattest 0.002s
# floattest [floattest.test]
./main_1_13_test.go:10:14: hexadecimal floating-point literals requires go1.13 or later (-lang was set to go1.11; check go.mod)
FAIL floattest [build failed]
Since the build settings will not compile this file on go < 1.13, this shouldn't be an error.
But you use go.1.13.10 to run go test, so the file is built.
Yes, so there should be no error, since go 1.13 supports hex float notation.
You specified go 1.11 in go.mod, so I'd say that's expected, it'd actually be a bug if it worked.
So how to I make my project buildable under 1.11? I've put the 1.13 stuff in a +build guarded file so that it only builds the 1.13 stuff when building with go 1.13.
So how to I make my project buildable under 1.11? I've put the 1.13 stuff in a
+buildguarded file so that it only builds the 1.13 stuff when building with go 1.13.
Use go1.11.x or 1.12.x to build.
Or maybe drop support for go < 1.13, set go1.13 in go.mod
It builds fine under 1.11 and 1.12. It only fails when I try to build using 1.13.
Dropping support for 1.11 and 1.12 seems a silly thing to do when it builds fine under those versions. This is a problem with two compiler rules fighting each other, not a rational thing.
I think this should work. Having a go1.11 mark in the mod file means we shouldn't define a go1.13 build tag.
The bad code never makes it to the compiler. Something earlier in the toolchain is barfing on the input.
@bcmills
It builds fine under 1.11 and 1.12. It only fails when I try to build using 1.13.
Dropping support for 1.11 and 1.12 seems a silly thing to do when it builds fine under those versions. This is a problem with two compiler rules fighting each other, not a rational thing.
I don't think it's silly.
Go is backward compatible, and also go1.11 and 1.12 are not supported anymore (see release policy)
@randall77 How about passing the current go version to -lang if the version is greater than the one specific in go.mod?
@kstenerud Doesn't doing something like this work for you? https://play.golang.org/p/nqejHFvguRv
-- go.mod --
module play.ground
go 1.13
@kortschak Change this to 1.11 and the problem returns.
So don't change it to go1.11? When you have go1.11 in the Go version specifier you are saying you want to use Go 1.11 features, but hex floats are a Go 1.13 feature.
Then that defeats the whole purpose. If go.mod specifies 1.13, then you can't build for <1.13, and foo_old.go is completely pointless since // +build !go1.13 will never be built.
The point is that I want to have my software package buildable in 1.11 and 1.12, but also use hex floats for more specific floating point test code when building in 1.13+.
More specifically: this code doesn't take the current +build settings into account to determine that the currently compiling file (with // +build go1.13) is restricted to 1.13 and up, but rather just fails based on the -lang flag.
Then that defeats the whole purpose. If
go.modspecifies1.13, then you can't build for <1.13, andfoo_old.gois completely pointless since// +build !go1.13will never be built.
This is not true. In the following session I build and run the code in the playground (with the exception that the float literal is negated in foo_old.go so that the code used is identified) in each version of Go from 1.11.9 to 1.14.2 (build chain is rebuilt for each version in another term).
~/foo $ go version
go version go1.11.9 linux/amd64
~/foo $ go build .
~/foo $ ./play.ground
-1.437696e+06
~/foo $ go version
go version go1.12.9 linux/amd64
~/foo $ go build .
~/foo $ ./play.ground
-1.437696e+06
~/foo $ go version
go version go1.13.9 linux/amd64
~/foo $ go build .
~/foo $ ./play.ground
1.437696e+06
~/foo $ go version
go version go1.14.2 linux/amd64
~/foo $ go build .
~/foo $ ./play.ground
1.437696e+06
Then this is exposing another issue. If go.mod specifies 1.13, why are the go 1.11 and 1.12 compilers not detecting this and throwing an error?
If the version in go.mod is ignored by the compiler, what's it for?
It is to indicate language features that are required. The question you are asking is #30791.
See specifically https://github.com/golang/go/issues/31747#issuecomment-488353818.
Duplicate of #30791
Most helpful comment
I think this should work. Having a go1.11 mark in the mod file means we shouldn't define a go1.13 build tag.
The bad code never makes it to the compiler. Something earlier in the toolchain is barfing on the input.
@bcmills