"testing"
"test/smallint"
)
func BenchmarkConvert(b *testing.B) {
for i := 0; i < b.N; i++ {
result := smallint.Convert(12)
_ = result
}
}
分别使用 Go1.14 和 Go1.15 版本进行测试:
$ go version
go version go1.14.7 darwin/amd64
$ go test -bench . -benchmem ./...
goos: darwin
goarch: amd64
pkg: test/smallint
BenchmarkConvert-8 569830 1966 ns/op 2592 B/op 101 allocs/op
PASS
ok test/smallint 1.647s
$ go version
go version go1.15 darwin/amd64
$ go test -bench . -benchmem ./...
goos: darwin
goarch: amd64
pkg: test/smallint
BenchmarkConvert-8 1859451 655 ns/op 1792 B/op 1 allocs/op
PASS
ok test/smallint 2.178s
接着讲 smallint_test.go 中调用 Convert 的参数由 12 改为 256,再次使用 Go1.15 运行,结
果如下:
$ go test -bench . -benchmem ./...
goos: darwin
goarch: amd64
pkg: test/smallint
BenchmarkConvert-8 551546 2049 ns/op 2592 B/op 101 allocs/op
PASS
ok test/smallint 1.502s
证明了上面提到的优化点。
那么,你想过它大概怎么实现的吗?因为上文提到,Go 中接口的实现,使用一个指针字段指向接
口值。现在竟然不再额外进行内存分配,说明做了什么特殊的事情。
其实答案非常简单。如果你对 Python、Java 等语言熟悉,应该知道大概如何实现的。Go 中如何
做的,可以在 中(合并到 中了,GitHub 上更易于阅读)找到。具体Go CL 216401[3] 此提交[4]
来说就是 Go 中定义了一个特殊的静态数组,该数组由 256 个整数组成(0 到 255)。当必须分
配内存以将整数存储在堆上,并将其转换为接口的一部分时,它首先检查是否它可以只返回指向