Go 字串連線+=與strings.Join效能對比
阿新 • • 發佈:2018-12-10
Go字串連線
對於字串的連線大致有兩種方式:
1、通過+號連線
func StrPlus1(a []string) string {
var s, sep string
for i := 0; i < len(a); i++ {
s += sep + a[i]
sep = " "
}
return s
}
2、通過strings.Join連線
func StrPlus2(a []string) string {
return strings.Join(a, " ")
}
對比兩種方式的效率,通過壓力測試進行對比
import "testing"
func BenchmarkStrPlus1(b *testing.B) {
for i := 0; i < b.N; i++ {
StrPlus1([]string{"xxx", "bbb", "aaa"})
}
}
func BenchmarkStrPlus2(b *testing.B) {
for i := 0; i < b.N; i++ {
StrPlus2([]string{"xxx", "bbb", "aaa"})
}
}
執行壓力測試go test -test.bench=".*"
goos: darwin
goarch: amd64
BenchmarkStrPlus1-4 10000000 127 ns/op
BenchmarkStrPlus2-4 20000000 78.7 ns/op
從本機來看通過+號連線字串每個操作消耗127ns時間,strings.Join消耗78.7ns。效率上strings.Join更高
來看下strings包中Join的實現
// Join concatenates the elements of a to create a single string. The separator string // sep is placed between elements in the resulting string. func Join(a []string, sep string) string { switch len(a) { case 0: return "" case 1: return a[0] case 2: // Special case for common small values. // Remove if golang.org/issue/6714 is fixed return a[0] + sep + a[1] case 3: // Special case for common small values. // Remove if golang.org/issue/6714 is fixed return a[0] + sep + a[1] + sep + a[2] } n := len(sep) * (len(a) - 1) for i := 0; i < len(a); i++ { n += len(a[i]) } b := make([]byte, n) bp := copy(b, a[0]) for _, s := range a[1:] { bp += copy(b[bp:], sep) bp += copy(b[bp:], s) } return string(b) }
可以看出當連線字串數量較大時,是先通過make分配足夠的空間,然後把每個字串copy到空間裡面,而不是每次通過+號來多次分配記憶體。