strings.Builder accumulates text in an internal byte buffer, then exposes the result with String. It suits incremental string construction when repeated concatenation would create unnecessary allocation work, and it can also retain output written through an io.Writer interface for later inspection. section 3.2.4 section 5.4.1
Build a URL with one planned allocation
Estimate the final length, call Grow once, then append each optional part with WriteString or WriteByte. The resulting String returns the completed URL text. Grow is most useful when a reasonable final size is known; without it, the buffer may need to allocate again as it fills. section 3.2.4
Listing 3.10 Optimizing the String method (url/url.go)
func (u *URL) String() string {
if u == nil {
return ""
}
const (
lenSchemeSeparator = len("://") #1
lenPathSeparator = len("/") #1
)
lenURL := len(u.Scheme) + lenSchemeSeparator + #2
len(u.Host) + lenPathSeparator + #2
len(u.Path) #2
var s strings.Builder #3
s.Grow(lenURL) #4
if sc := u.Scheme; sc != "" {
s.WriteString(sc) #5
s.WriteString("://") #5
}
if h := u.Host; h != "" {
s.WriteString(h) #5
}
if p := u.Path; p != "" {
s.WriteByte('/') #6
s.WriteString(p) #5
}
return s.String() #7
}
This complete URL formatter shows the practical sequence: compute capacity, grow the builder, append delimiters and fields conditionally, then return String. section 3.2.4
A Builder can be used as an io.Writer. That makes it useful in tests: assign one to output fields typed as io.Writer, run the program, and compare builder.String() with the expected standard-output or error-output text. A Writer itself cannot be read back, but Builder keeps the written data for String to retrieve. section 5.2.3 section 5.4.1
Capture CLI output in a test
Declare a zero-value Builder, provide it where a CLI expects an io.Writer, execute the CLI, and inspect String afterward. The zero value is ready to use, even though WriteString and related methods have pointer receivers: calling them on an addressable Builder variable lets Go supply its address automatically. section 5.4 section 5.4.1
Use Builder with a few important boundaries in mind:
- Prefer it when accumulating bytes or strings and ultimately reading one string; bytes.Buffer has a similar API and is commonly used for incrementally collected byte data such as logs and HTTP request bodies. section 3.2.4
- Do not copy a Builder after it has been used. Its internal buffer means passing it by value to other functions can panic or behave unexpectedly; pass a pointer instead. section 5.4.1
- Use WriteString for text and WriteByte for single-byte separators; finish with String rather than manually converting the internal bytes. section 3.2.4


