liveBook · Manning

String

As explained in 100 Go Mistakes and How to Avoid Them

A string is a Go value representing an immutable sequence of arbitrary bytes, conventionally containing UTF-8 text.

A Go string is an immutable sequence of arbitrary bytes, represented by a pointer and a byte count. UTF-8 source literals contain UTF-8 bytes, but a string obtained elsewhere need not be UTF-8. `len(s)` counts bytes, not runes; a rune is a Unicode code point. section 5.0 section 5.1

A byte index is not a rune index

For `s := "hêllo"`, `len(s)` is 6, although the string has five runes. In `for i := range s`, the indexes are byte offsets: 0, 1, 3, 4, and 5. Printing `s[i]` at offset 1 prints the first byte of `ê`, not `ê`. Use `for i, r := range s` to print each rune with its byte offset; convert to `[]rune` when rune-numbered indexes are needed. section 5.2

Choose the representation and operation that match the job:

  • For repeated concatenation, `s += value` creates a new string on each iteration. Use `strings.Builder`; call `Grow` when the final byte length is known. Do not use one builder concurrently. section 5.4
  • For `[]byte` data read through `io.Reader`, avoid converting to string and back just to trim whitespace. `bytes.TrimSpace` keeps the operation in bytes and avoids those conversion allocations. section 5.5
  • A substring such as `s[:5]` selects five bytes, not five runes. For rune-based slicing, slice `[]rune(s)` instead. When retaining a small substring of a large string, use `strings.Clone` to avoid retaining the original backing storage. section 5.6

Substring storage sharing is not guaranteed by the Go specification. The standard Go compiler shares backing storage, which makes cloning useful when a short, long-lived substring comes from a large input. section 5.6

How 100 Go Mistakes and How to Avoid Them covers it

How deep it goes
Explains byte representation, rune offsets, allocation costs, and substring storage; qualifies storage sharing as compiler-dependent.
Examples
Contrasts incorrect and corrected iteration over `hêllo`, then extracts a short identifier from a large log message.
What it assumes
Assumes familiarity with basic Go loops, slices, and I/O while defining the rune and its relationship to UTF-8.
What you can do after
Apply it via `strings.Builder`, `bytes.TrimSpace`, and `strings.Clone` to avoid repeated copying, needless conversions, and retained buffers.
How it connects
Connects strings to Unicode code points, UTF-8, byte slices, and substring slicing.

Also explained in

Compare how 24 books explain string →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Go Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.