Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does golang strings.Builder implements String() like this?

Tags:

go

The implementation is

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

According to my test, converting []byte to string uses "copy on write", or the compiler generates the deep copy instructions if either one is changing the insided slice:

{
        a := []byte{'a'}
        s1 := string(a)
        a[0] = 'b'
        fmt.Println(s1) // a
    }

    {
        a := "a"
        b := []byte(a)
        b[0] = 'b'
        fmt.Println(a) // a
    }

So what happens if it's implemented as below?

// String returns the accumulated string.
func (b *Builder) String() string {
    return string(b.buf)
}
like image 761
Moon Avatar asked Dec 01 '22 09:12

Moon


1 Answers

You can view the discussion on the changelist that introduced the strings.Builder api here: https://go-review.googlesource.com/c/go/+/74931/4/src/strings/builder.go#30

As you'd expect, it's a discussion of API mechanics, correctness, and efficiency.

If you replace the code with string(b.buf), you'll cause a copy of the built string. It may be that the compiler optimizes away the copy in simple cases of converting a byte slice to a string, but it's very unlikely that the compiler can do that here in general (because it would require a proof that the buffer inside the string builder is never used again).

Note that the (standard-library) code looks dangerous, because if you write this:

var b strings.Builder
b.WriteString("hello world")
c := b.String()
b.WriteString("a")
d := b.String()

then c and d will end up pointing to the same memory. But that's fine, because strings contain the length of their buffer. And there's no way to mutate a string, because even though in theory the memory backing the string is accessible via the buf in the strings.Builder, the only apis provided append to the backed memory.

like image 167
Paul Hankin Avatar answered Dec 04 '22 15:12

Paul Hankin