Go version
go1.24.4
Output of go env in your module/workspace:
AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/apocalypse555/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/apocalypse555/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1252593989=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/home/apocalypse555/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/apocalypse555/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/apocalypse555/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/lib/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.24.4'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
I run go vet on this code :
func ok(a int) bool {
if a < 10 {
//panic(`with that, it's well detected`)
os.Exit(1)
return false
}
return true
}
(https://go.dev/play/p/CHtVr0fs-yw)
What did you see happen?
No warning like with panic().
What did you expect to see?
A warning like with panic().
It seems odd that an unreachable code is detected after a panic() but not after an os.Exit().
Related issue
https://github.com/golang/go/issues/53968
Comment From: randall77
Adding return false is required in many cases to adhere to the language spec on terminating statements.
func f(b bool) int {
if b {
return 5
} else {
os.Exit(1)
return 0 // doesn't compile without this line
}
}
The language spec doesn't say that os.Exit is a terminating statement. I'm not sure it should, as the spec doesn't mention specific packages very often. And changing the definition of terminating statement now would break existing programs.
I suppose vet could find code like the code in your case, where removing it doesn't invalidate the program. That's an extra complication, and I'm not sure how often such a constrained vet rule would trigger.
Comment From: cagedmantis
Comment From: adonovan
I did an experiment a long time ago to make cmd/vet smarter about dead code following calls to "no-return" functions. The ctrlflow analyzer already knows about such functions, so basing unreachable atop ctrflow would do most of the heavy lifting. I just shared some old prototype code in https://go.dev/cl/687635, but it needs some care to make it production-worthy.
I think the ideal behavior would be for the analyzer to offer a fix to turn any statement following a noreturn call into panic("unreachable").
Comment From: gopherbot
Change https://go.dev/cl/687635 mentions this issue: go/analysis/passes/unreachable: use ctrlflow analyzer
Comment From: TapirLiu
And runtime.Goexit. I'm surprised that it is not mentioned in Go spec at all. And its doc also doesn't mention the fact that if can cancel panics.
package main
import "runtime"
func main() {
var c = make(chan int)
go func() {
defer func() {
c <- 1
}()
defer func() {
runtime.Goexit() // cancel panic "bye"
}()
panic("bye")
}()
<-c
}
Comment From: seankhliao
seems like there's not a lot of code that has this problem, is this frequent enough for vet? https://github.com/search?q=language%3AGo+%2F%5E%5Cs%2Bos.Exit%5C%28.*%5C%29%5Cn%5Cs%2B%5Bae-os-z%5D%2F&type=code
regex is sort of limited, so search excludes: - [b]reak - [c]ase - [d]efault - [p]anic - [r]eturn - }
Comment From: adonovan
Here's the result of applying https://go.dev/cl/687635 to the Module Mirror corpus. It reported 7241 diagnostics in 24K modules (though many of those had build errors):
A quick inspection of ten at random shows that 7 are valid and 3 are signs of serious bugs in the analyzer: - https://go-mod-viewer.appspot.com/github.com/cznic/cc@v0.0.0-20181122101902-d673e9b70d4d/v2/ast2.go#L3771 - https://go-mod-viewer.appspot.com/github.com/Kucoin/kucoin-go-sdk@v1.2.18/order_test.go#L176 - https://go-mod-viewer.appspot.com/github.com/Augustu/go-micro/v2@v2.9.3/debug/log/kubernetes/kubernetes_test.go#L54
I guess I have more work to do here.
A random 50 are shown below.
https://go-mod-viewer.appspot.com/github.com/cloudwan/edgelq-sdk@v1.15.4/audit/resources/v1alpha2/common/common.pb.fieldpath.go#L2983: unreachable code https://go-mod-viewer.appspot.com/github.com/Kucoin/kucoin-go-sdk@v1.2.18/order_test.go#L176: unreachable code https://go-mod-viewer.appspot.com/github.com/cloudwan/edgelq-sdk@v1.15.4/alerting/resources/v1/common/specs.pb.fieldpath.go#L15077: unreachable code https://go-mod-viewer.appspot.com/github.com/ethereum/go-ethereum@v1.16.1/internal/cmdtest/test_cmd.go#L170: unreachable code https://go-mod-viewer.appspot.com/github.com/pachyderm/pachyderm@v1.13.4/src/server/admin/server/convert1_10.go#L488: unreachable code https://go-mod-viewer.appspot.com/github.com/epsagon/epsagon-go@v1.39.0/example/s3_example/write/main.go#L58: unreachable code https://go-mod-viewer.appspot.com/github.com/snikch/goodman@v0.0.0-20171125024755-10e37e294daa/example/main.go#L23: unreachable code https://go-mod-viewer.appspot.com/github.com/cloudwan/edgelq-sdk@v1.15.4/logging/client/v1alpha2/log_descriptor/log_descriptor_service.pb.descriptors.go#L1351: unreachable code https://go-mod-viewer.appspot.com/github.com/cznic/cc@v0.0.0-20181122101902-d673e9b70d4d/v2/ast2.go#L3771: unreachable code https://go-mod-viewer.appspot.com/github.com/Augustu/go-micro/v2@v2.9.3/debug/log/kubernetes/kubernetes_test.go#L54: unreachable code https://go-mod-viewer.appspot.com/github.com/whiteCcinn/protobuf-go@v1.0.9/internal/testprotos/legacy/proto2_20160225_2fc053c5/test.pb.go#L1826: unreachable code https://go-mod-viewer.appspot.com/github.com/CESSProject/cess-go-sdk@v0.7.2/example/chain/parseblock/parseblock.go#L120: unreachable code https://go-mod-viewer.appspot.com/github.com/aws/aws-encryption-sdk/releases/go/encryption-sdk@v0.2.0/KeyDerivation/KeyDerivation.go#L448: unreachable code https://go-mod-viewer.appspot.com/sourcegraph.com/sourcegraph/go-vcs@v0.0.0-20230717073621-ca41431d1b7d/vcs/git/repo.go#L296: unreachable code https://go-mod-viewer.appspot.com/github.com/cloudwan/edgelq-sdk@v1.15.4/monitoring/resources/v4/alert/alert.pb.fieldpath.go#L3327: unreachable code https://go-mod-viewer.appspot.com/github.com/conbanwa/logs@v0.4.7/compare.go#L176: unreachable code https://go-mod-viewer.appspot.com/github.com/aws/aws-cryptographic-material-providers-library/releases/go/smithy-dafny-standard-library@v0.2.0/Actions/Actions.go#L191: unreachable code https://go-mod-viewer.appspot.com/github.com/Venafi/vcert/v5@v5.10.2/pkg/venafi/tpp/connector_test.go#L577: unreachable code https://go-mod-viewer.appspot.com/github.com/Kucoin/kucoin-go-sdk@v1.2.18/margin_test.go#L294: unreachable code https://go-mod-viewer.appspot.com/github.com/charlesetsmith/saratoga/sarflags@v0.0.0-20240223233549-4e862e6c4217/sarflags.go#L807: unreachable code https://go-mod-viewer.appspot.com/github.com/cockroachdb/pebble@v1.1.5/scan_internal_test.go#L337: unreachable code https://go-mod-viewer.appspot.com/github.com/aws/aws-cryptographic-material-providers-library/releases/go/mpl@v0.2.0/IntermediateKeyWrapping/IntermediateKeyWrapping.go#L526: unreachable code https://go-mod-viewer.appspot.com/github.com/cloudwan/edgelq-sdk@v1.15.4/applications/resources/v1alpha2/pod/pod.pb.fieldpath.go#L3007: unreachable code https://go-mod-viewer.appspot.com/github.com/vishvananda/netlink@v1.3.1/filter_test.go#L1146: unreachable code https://go-mod-viewer.appspot.com/github.com/decred/dcrlnd@v0.7.6/cmd/dcrlncli/cmd_open_channel.go#L587: unreachable code https://go-mod-viewer.appspot.com/github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/index/writer.go#L1399: unreachable code https://go-mod-viewer.appspot.com/github.com/core-coin/go-core@v1.1.7/p2p/discover/ntp_test.go#L25: unreachable code https://go-mod-viewer.appspot.com/github.com/network-quality/goresponsiveness@v0.0.0-20240129151524-343954285090/probe/tracer.go#L113: unreachable code https://go-mod-viewer.appspot.com/github.com/core-coin/go-core@v1.1.7/p2p/discover/ntp_test.go#L31: unreachable code https://go-mod-viewer.appspot.com/github.com/theQRL/go-zond@v0.2.1/trie/stacktrie_test.go#L329: unreachable code https://go-mod-viewer.appspot.com/github.com/TIBCOSoftware/flogo-lib@v0.5.9/core/mapper/exprmapper/expression/expression_test.go#L263: unreachable code https://go-mod-viewer.appspot.com/github.com/xujiajun/gorouter@v1.2.0/router_test.go#L219: unreachable code https://go-mod-viewer.appspot.com/github.com/epsagon/epsagon-go@v1.39.0/example/sts_example/main.go#L41: unreachable code https://go-mod-viewer.appspot.com/github.com/luckypickle/go-ethereum-vet@v1.14.2/signer/rules/rules_test.go#L521: unreachable code https://go-mod-viewer.appspot.com/github.com/cznic/fileutil@v0.0.0-20181122101858-4d67cfea8c87/storage/probe_test.go#L44: unreachable code https://go-mod-viewer.appspot.com/github.com/symfony-cli/console@v1.2.1/flag_test.go#L1229: unreachable code https://go-mod-viewer.appspot.com/github.com/whiteCcinn/protobuf-go@v1.0.9/internal/testprotos/legacy/proto3_20160225_2fc053c5/test.pb.go#L758: unreachable code https://go-mod-viewer.appspot.com/github.com/btnguyen2k/consu/semita@v0.1.5/Semita_test.go#L2543: unreachable code https://go-mod-viewer.appspot.com/github.com/uber-go/tally/v4@v4.1.17/thirdparty/github.com/apache/thrift/lib/go/thrift/protocol_test.go#L109: unreachable code https://go-mod-viewer.appspot.com/github.com/cohesity/app-sdk-go@v0.0.0-20190722230114-5dbb9337cc19/unirest-go/Request.go#L131: unreachable code https://go-mod-viewer.appspot.com/github.com/nicocha30/gvisor-ligolo@v0.0.0-20250509122847-3be646365354/pkg/abi/linux/linux_abi_autogen_unsafe.go#L5436: unreachable code https://go-mod-viewer.appspot.com/github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/debug/log/kubernetes/kubernetes_test.go#L44: unreachable code https://go-mod-viewer.appspot.com/modernc.org/cc@v1.0.1/v2/ast2.go#L3894: unreachable code https://go-mod-viewer.appspot.com/github.com/gogf/gf@v1.16.9/database/gdb/gdb_z_mysql_transaction_test.go#L1069: unreachable code https://go-mod-viewer.appspot.com/github.com/btnguyen2k/consu/semita@v0.1.5/Semita_test.go#L2087: unreachable code https://go-mod-viewer.appspot.com/github.com/cloudwan/edgelq-sdk@v1.15.4/monitoring/client/v4/project/project_service.pb.descriptors.go#L1448: unreachable code https://go-mod-viewer.appspot.com/github.com/terraform-linters/tflint-plugin-sdk@v0.22.0/plugin/internal/plugin2host/plugin2host_test.go#L749: unreachable code https://go-mod-viewer.appspot.com/github.com/glycerine/goconvey@v0.0.0-20190410193231-58a59202ab31/convey/assertions/ignorespaces.go#L330: unreachable code https://go-mod-viewer.appspot.com/github.com/cloudwan/edgelq-sdk@v1.15.4/devices/resources/v1/device/device.pb.fieldpath.go#L18980: unreachable code https://go-mod-viewer.appspot.com/github.com/hashicorp/terraform-plugin-sdk@v1.17.2/terraform/upgrade_state_v1_test.go#L68: unreachable code ecosystem$