go version)?$ go version go version go1.14rc1 linux/amd64
Yes.
go env)?go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN="/home/manlio/.local/bin"
GOCACHE="/home/manlio/.cache/go-build"
GOENV="/home/manlio/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/manlio/.local/lib/go:/home/manlio/src/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/manlio/sdk/go1.14rc1"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/manlio/sdk/go1.14rc1/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
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-build423783759=/tmp/go-build -gno-record-gcc-switches"
GOROOT/bin/go version: go version go1.14rc1 linux/amd64
GOROOT/bin/go tool compile -V: compile version go1.14rc1
uname -sr: Linux 5.5.2-arch1-1
/usr/lib/libc.so.6: GNU C Library (GNU libc) stable release version 2.31.
gdb --version: GNU gdb (GDB) 8.3.1
https://play.golang.org/p/SZZ4gDss0DK
The program to be compiled.
/prog.go:13:1: missing return at end of function
The Go compiler does not know that runtime.Goexit causes the function to exit, so the return statement is unreachable and not required.
Of course there are similar functions like os.Exit, but Goexit is part of the runtime, so it should probably be recognized by the compiler.
On the other hand, vet should know about runtime.Goexit and should report that the statements after Goexit() are not reachable.
The compile or vet commands should also report an error if a function used in the go statement has a non empty result in the signature, but this is a different issue and probably there is a reason why it does not report an error.
The relevant bit of the spec is https://golang.org/ref/spec#Terminating_statements. I鈥檇 personally be reluctant to add runtime.Goexit; everything else in that list is lower level.
It is important for vet to use the same set of terminating statements as the compiler. Otherwise you鈥檒l be forced to add a terminating statement in some cases (like this) to make your code compile but vet will then complain about it.
The Goexit function really acts as a low level API: https://github.com/golang/go/issues/29226
/cc @randall77 @griesemer per owners.
The definition of "terminating statements" is based strictly on properties of the language spec (which are unlikely to change), not APIs (which may change).
Also, even if we added runtime.Goexit it wouldn't be satisfactory anyway: It's not unlikely that runtime.Goexit is factored out into a function that does cleanups or perhaps prints additional error information; thus it is that function that will be called (possibly from multiple places) in a program. And unless we propagate the "exit" information to the caller, knowing that runtime.Goexit doesn't return won't be very helpful - it'll save a single return statement. That doesn't seem worth it.
More precisely, runtime.Goexit doesn't terminate the function, it terminates the goroutine that calls it. If we wanted to capture that correctly, we'd need to propagate that up the call stack, with extra rules. I am not convinced this is worth the extra complexity or the mixing of language spec and library APIs.
Not really a proposal, but leaving open for a decision by the proposal review commitee.
I've found a bunch of times where I call t.Fatal in a testing utility but I still need to return, so instead I currently add switch{} after the fatal calls,
adding some attribute(like C++'s noreturn) or even type (like Rust's Never type(!)) would be really useful even if it would be limited to the standard library only
Most helpful comment
The definition of "terminating statements" is based strictly on properties of the language spec (which are unlikely to change), not APIs (which may change).
Also, even if we added
runtime.Goexitit wouldn't be satisfactory anyway: It's not unlikely thatruntime.Goexitis factored out into a function that does cleanups or perhaps prints additional error information; thus it is that function that will be called (possibly from multiple places) in a program. And unless we propagate the "exit" information to the caller, knowing thatruntime.Goexitdoesn't return won't be very helpful - it'll save a singlereturnstatement. That doesn't seem worth it.More precisely,
runtime.Goexitdoesn't terminate the function, it terminates the goroutine that calls it. If we wanted to capture that correctly, we'd need to propagate that up the call stack, with extra rules. I am not convinced this is worth the extra complexity or the mixing of language spec and library APIs.Not really a proposal, but leaving open for a decision by the proposal review commitee.