问题引入
- Golang中的string类型是只读且不可变的。因此通过循环字符串切片拼接字符串的方式会导致大量的string创建、销毁和内存分配
解决方法
通过bytes.Buffer优化
- 使用
var bs bytes.Buffer
存放最终拼接好的字符串,一定程度上避免了string每进行一次拼接都重新申请内存空间的问题 - 但依然存在一个问题:最终byte数组强转string,同样需要进行一次内存分配和内容拷贝
func (b *Buffer) String() string {
if b == nil {
// Special case, useful in debugging.
return "<nil>"
}
return string(b.buf[b.off:])
}
通过strings.Builder优化
- 优化一:针对最终byte数组转换string进行优化,使用了一个
unsafe.Pointer
的内存指针转换操作,避免了内存分配的问题
func (b *Builder) String() string {
return *(*string)(unsafe.Pointer(&b.buf))
}
- 优化二:通过
copyCheck()
来保证Builder对象被赋值后不可修改,来避免byte数组逃逸到堆上
func (b *Builder) copyCheck() {
if b.addr == nil {
b.addr = (*Builder)(noescape(unsafe.Pointer(b)))
} else if b.addr != b {
panic("strings: illegal use of non-zero Builder copied by value")
}
}
标签:string,Builder,unsafe,Golang,拼接,内存,字符串,addr
From: https://blog.51cto.com/u_16263554/7473904