Go: 判断空字符串的性能比较

Jan 23 2019 Golang

字符串在 Go 内部中是一个结构体,一个字段记录长度,一个字段记录指针位置。

判断字符串为空最常见的是 data == "" 这样,之前我认为这里分配了一个空字符串会占用分配的时间,所以我把一些判断都改成了 len(data) == 0 这样就不用分配一个空字符串的空间了,效率应该会提升。

1
2
3
4
5
6
7
8
9
10
11
package main

import (
"fmt"
"unsafe"
)

func main() {
data := ""
fmt.Println(unsafe.Sizeof(data)) // 输出 16
}

但最近我在 Go 源码中看到很多使用第一种判断是否为空的写法,这让我有点怀疑是否我的优化是否正确。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package comp

func isEmptyString0() bool {
var data string
if data == "" {
return true
}
return false
}

func isEmptyString1() bool {
var data string
if len(data) == 0 {
return true
}
return false
}
`

测试后,发现二者在性能上几乎没有区别。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package comp

import "testing"

func BenchmarkIsEmptyString0(b *testing.B) {
for i := 0; i < b.N; i++ {
isEmptyString0()
}
}

func BenchmarkIsEmptyString1(b *testing.B) {
for i := 0; i < b.N; i++ {
isEmptyString1()
}
}

测试输出:

1
2
3
4
5
6
7
8
goos: windows
goarch: amd64
pkg: github.com/islishude/test/str
BenchmarkIsEmptyString0-8 2000000000 0.30 ns/op 0 B/op 0 allocs/op
BenchmarkIsEmptyString1-8 2000000000 0.30 ns/op 0 B/op 0 allocs/op
PASS
ok github.com/islishude/test/comp1.541s
Success: Benchmarks passed.

结果一致,另外看到内存也都没有,这说明 go 在编译时已经对这个做了优化。