为什么 string.Builder Reset() 不保留底层缓冲区?

Why doesn’t string.Builder Reset() preserve the underlying buffer?

// Reset resets the Builder to be empty.
func (b *Builder) Reset() {
    b.addr = nil
    b.buf = nil
}

代码片段来自go strings.Builder中的源代码。缓冲区设置为 nil 而不是 b.buf[:0]。将其设置为 nil 而不是保留容量的原因是什么?

编辑: 我可以看到 Reset() 可用于 GC 底层缓冲区并允许重新使用 Builder 结构,但初始化结构似乎是边际成本,因为它只是两个指针,而底层数组可能更大,并且可以重复使用。我觉得应该有一个 Clear() 函数来保持底层缓冲区的容量但将其长度减少到 0,而且实现起来很简单。这让我相信没有这样做是有原因的,我很好奇那个原因是什么。

Reset() 的要点是让 Builder 进入初始空状态(就像创建新状态时一样)。

这样做而不是获取新的 Builder 的好处是,当您的程序的其他组件持有对现有 Builder 的引用并且您想 "reset" 它到初始状态而不使用新引用刷新所有这些组件。

如果 Reset 保留了底层缓冲区,那么一个长期存在的 Builder 将占用它所构建的最长字符串的内存。分配给最长字符串的数组将始终处于活动状态,即使其中大部分未被使用。将缓冲区设置为 nil 允许垃圾收集器收集此类潜在的大缓冲区。

strings.Builder 的优化之一是在将 []byte 转换为 string 时不复制字节。看看它的String()方法:

// String returns the accumulated string.
func (b *Builder) String() string {
    return *(*string)(unsafe.Pointer(&b.buf))
}

这意味着重复使用缓冲区会破坏以前创建的字符串。

这是操场上的证明:https://play.golang.org/p/gkSXRwi0-Ff