Strings and I/O: Zero-Allocation Conversions and Buffer Choices

Strings and I/O: Zero-Allocation Conversions and Buffer Choices

Zero-allocation conversion between string and []byte

func String(b []byte) string {
 return *(*string)(unsafe.Pointer(&b))
}

func Str2Bytes(s string) []byte {
 x := (*[2]uintptr)(unsafe.Pointer(&s))
 h := [3]uintptr{x[0], x[1], x[1]}
 return *(*[]byte)(unsafe.Pointer(&h))
}

I/O Operations

bufio.Reader vs bytes.Buffer

bufio reduces system calls for read and write operations by wrapping io.Reader and io.Writer interfaces. bytes.Buffer stores variable-length []byte slices efficiently.

bytes.Buffer vs strings.Builder

For Go 1.10 and later, use strings.Builder to store variable-length []byte slices. This avoids expensive copying. strings.Builder appends directly to its underlying array and returns strings with zero allocation.

strings.Builder’s growth strategy:

  1. If growth length N is ≤ cap-len, don’t expand
  2. Otherwise allocate new underlying array with capacity 2*cap + N and copy old data

Note that neither is safe for concurrent writes.