https://github.com/golang/go/blob/master/src/strings/builder.go
主要的作用是频繁拼接字符串,相比字符串拼接操作符(+
)或者 fmt.SPrintf
效率更高。
实例
package main
import (
"fmt"
"strings"
)
func main() {
var builder strings.Builder
builder.WriteString("Hello")
builder.WriteString(", ")
builder.WriteString("World!")
result := builder.String()
fmt.Println(result)
}
方法
func (b *Builder) String() string
func (b *Builder) Len() int { return len(b.buf)
func (b *Builder) Cap() int { return cap(b.buf)
func (b *Builder) Reset()
内容重置func (b *Builder) Grow(n int)
预分配空间,正确使用可以提升程序执行效率func (b *Builder) Write(p []byte) (int, error)
func (b *Builder) WriteByte(c byte) error
func (b *Builder) WriteRune(r rune) (int, error)
func (b *Builder) WriteString(s string) (int, error)
源码
实际上就是针对 []byte
的一个封装。
// A Builder is used to efficiently build a string using Write methods.
// It minimizes memory copying. The zero value is ready to use.
// Do not copy a non-zero Builder.
type Builder struct {
addr *Builder // of receiver, to detect copies by value
buf []byte
}
func (b *Builder) copyCheck() {
if b.addr == nil {
// This hack works around a failing of Go's escape analysis
// that was causing b to escape and be heap allocated.
// See issue 23382.
// TODO: once issue 7921 is fixed, this should be reverted to
// just "b.addr = b".
b.addr = (*Builder)(noescape(unsafe.Pointer(b)))
} else if b.addr != b {
panic("strings: illegal use of non-zero Builder copied by value")
}
}
// WriteString appends the contents of s to b's buffer.
// It returns the length of s and a nil error.
func (b *Builder) WriteString(s string) (int, error) {
b.copyCheck()
b.buf = append(b.buf, s...)
return len(s), nil
}
addr
指向自己的指针,不知道干什么用buf
是 buffer,缓冲区,用于存储 build 出来的字符串- 通过缓冲区做存储,避免频繁创建字符串对象,减少内存分配和垃圾回收
性能测试
BenchmarkStrPlus-20 100000000 11.11 ns/op 0 B/op 0 allocs/op
BenchmarkSprintf-20 12129922 101.5 ns/op 48 B/op 3 allocs/op
BenchmarkStrJoin-20 45257742 24.47 ns/op 16 B/op 1 allocs/op
BenchmarkStrBuilder-20 38868284 36.31 ns/op 24 B/op 2 allocs/op
BenchmarkByteBuf-20 22016934 53.34 ns/op 80 B/op 2 allocs/op
BenchmarkByteSlice-20 31495318 36.13 ns/op 24 B/op 2 allocs/op
BenchmarkByteSlice2-20 39563612 32.18 ns/op 24 B/op 2 allocs/op
BenchmarkStrPlusBatch-20 7331364 170.0 ns/op 112 B/op 6 allocs/op
BenchmarkSprintfBatch-20 1481492 823.2 ns/op 328 B/op 20 allocs/op
BenchmarkStrJoinBatch-20 19598844 59.78 ns/op 32 B/op 1 allocs/op
BenchmarkStrBuilderBatch-20 13560961 87.39 ns/op 56 B/op 3 allocs/op
BenchmarkByteBufBatch-20 10693280 97.61 ns/op 96 B/op 2 allocs/op
BenchmarkByteSliceBatch-20 12115166 95.27 ns/op 56 B/op 3 allocs/op
BenchmarkByteSlice2Batch-20 13136418 90.53 ns/op 56 B/op 3 allocs/op
fmt.Sprintf 用来做字符串拼接的话,性能总是最差。
此外,如果只是简单的两个字符串相加,直接加号拼接性能最好。
否则就根据情况,选用其他方案比较好。