strings.Builder类型的值(以下简称Builder值)的优势有下面的三种:
已存在的内容不可变,但可以拼接更多的内容;
减少了内存分配和内容拷贝的次数;
可将内容重置,可重用值。
先来说说string类型。
我们都知道,在 Go 语言中,string类型的值是不可变的。 如果我们想获得一个不一样的字符串,那么就只能基于原字符串进行裁剪、拼接等操作,从而生成一个新的字符串。裁剪操作可以使用切片表达式;拼接操作可以用操作符+实现。
因为string类型底层是数组,每次扩容都需要重新分配内存,性能是有损耗的
Builder值的优势其实主要体现在字符串拼接方面
Builder值中有一个用于承载内容的容器(以下简称内容容器)。它是一个以byte为元素类型的切片(以下简称字节切片)。
切片可以预分配容量,因此不需要反复分配内存
由于这样的字节切片的底层数组就是一个字节数组,所以我们可以说它与string值存储内容的方式是一样的。
实际上,它们都是通过一个unsafe.Pointer类型的字段来持有那个指向了底层字节数组的指针值的。
var builder1 strings.Builder builder1.WriteString("A Builder is used to efficiently build a string using Write methods.") fmt.Printf("The first output(%d): %q ", builder1.Len(), builder1.String()) fmt.Println() builder1.WriteByte(' ') builder1.WriteString("It minimizes memory copying. The zero value is ready to use.") builder1.Write([]byte{' ', ' '}) builder1.WriteString("Do not copy a non-zero Builder.") fmt.Printf("The second output(%d): "%s" ", builder1.Len(), builder1.String()) fmt.Println() // 示例2。 fmt.Println("Grow the builder ...") builder1.Grow(10) //扩容字节切片 fmt.Printf("The length of contents in the builder is %d. ", builder1.Len()) fmt.Println() // 示例3。 fmt.Println("Reset the builder ...") builder1.Reset() //重置内容 fmt.Printf("The third output(%d): %q ", builder1.Len(), builder1.String())