go install go101.org/gotv@latest
gotv 1.17. version gotv 1.18. version gotv 1.19. version
gotv
command needs to pull the Go language project, so it might need several minutes to finish.
x
can be converted to type T
if x
is a string and T
is a slice of bytes, and vice versa.
[]byte
.
byte
.
f
in the following code is valid but thinks the function g
is invalid.
package main
type T byte
//go:noinline
func f(s string) []T {
return []T(s)
}
//go:noinline
func g(x []T) string {
return string(x) // error (line 12)
}
func main() {
_ = f("Go")
_ = g([]T{71, 111})
}
$ gotv 1.17. run main.go [Run]: $HOME/.cache/gotv/tag_go1.17.13/bin/go run main.go # command-line-arguments ./main.go:12:15: cannot use <node SPTR> (type *T) as type *byte in argument to runtime.slicebytetostring $ gotv 1.18. run main.go [Run]: $HOME/.cache/gotv/tag_go1.18.7/bin/go main main.go
[]T
as a slice of bytes (in the function f
), sometimes doesn't (in the function g
). If the type T byte
type definition is changed into a type alias declaration type T = byte
, then the function g
is also viewed as valid by the official standard Go compiler 1.17.
reflect
standard package has not been updated accordingly. For example, the following program prints two false
, but should print two true
instead.
package main
import "reflect"
type T byte
func main() {
var s string
var x []T
var sType = reflect.TypeOf(s)
var xType = reflect.TypeOf(x)
println(sType.ConvertibleTo(xType))
println(xType.ConvertibleTo(sType))
}
package main
func main() {
const (
iota = iota
Y
)
println(Y)
}
1
, which is actually the answer of the official standard Go compiler 1.17.13-. However, since the official standard Go compiler 1.18, the answer is 0
. The followings are the outputs with different compiler versions:
$ gotv 1.17. run main.go [Run]: $HOME/.cache/gotv/tag_go1.17.13/bin/go run main.go 1 $ gotv 1.18. run main.go [Run]: $HOME/.cache/gotv/tag_go1.18.7/bin/go run main.go 0
package main
func main() {
const (
iota = iota
Y = iota
)
println(Y)
}
iota
is the local declared iota
, which value is 0
.
false
, but it prints true
when using the official standard Go compiler from version 1.8 to 1.17.13.
package main
type T struct{}
type S = T
type A = struct{ T }
type B = struct{ S }
func main() {
var a A
var b B
println(interface{}(b) == interface{}(a))
}
A
and B
denote different types (with different field names), which is why the comparison should result false
.
$ gotv 1.17. run main.go [Run]: $HOME/.cache/gotv/tag_go1.17.13/bin/go run main.go true $ gotv 1.18. run main.go [Run]: $HOME/.cache/gotv/tag_go1.18.7/bin/go run main.go false
package main
import "runtime"
func main() {
c := make(chan struct{})
go func() {
defer close(c)
defer runtime.Goexit()
panic("bye")
}()
<-c
}
"bye"
panic is never recovered. But in the implementation of the official standard Go runtime, a Goexit signal will cancel already happened (recoverable) panics in the current goroutine. So, with the official standard compiler, the above program will exit normally. The behavior was decided as correct in Go 1.19.
runtime.Goexit
calls act as super recover
calls. For example, the following two goroutine functions behave the same.
func goroutine1() {
defer runtime.Goexit()
panic(1)
}
func goroutine2() {
defer func() {
recover()
}()
panic(1)
}
The Go 101 project is hosted on Github. Welcome to improve Go 101 articles by submitting corrections for all kinds of mistakes, such as typos, grammar errors, wording inaccuracies, description flaws, code bugs and broken links.
If you would like to learn some Go details and facts every serveral days, please follow Go 101's official Twitter account @zigo_101.