When would you use String Iteration in a real project
Fast recall
Quick revision
Core answer
Practical understanding of String Iteration.
Repeating a definition without saying when to use it.
Give one trade-off and say how you would test it.
Interview-ready guide
Interview answer
Both yield runes — the difference is where the runes live:
// range over the string — decoded on the fly, zero allocation
for i, r := range s { ... } // i = byte offset
// range over the materialized slice — one allocation, done
rs := []rune(s)
for i, r := range rs { ... } // i = slice index (== rune index)The string range decodes each rune in registers as it walks — nothing is stored. The slice range iterates an int32 array that was fully built (O(n) allocation, decode pass already paid).
When the materialized version is right: (1) you need rune indices, not byte offsets (the i differs — byte offsets skip past wide runes); (2) you need MULTIPLE passes (sort the runes, reverse, scan twice — one decode, many iterations); (3) you need random access (rs[k] for various k). For any of those, []rune(s) once, then work the slice.
When the string range is right: everything else — single pass, no stored runes, no allocation. The common waste: []rune(s) inside a function called per-item — the conversion allocates every call when a range (or a single pass with utf8 functions) needed nothing stored.
When would you use String Iteration in a real project
Direct Answer
range s decodes runes on the fly (no allocation, byte offsets). range []rune(s) iterates a materialized int32 slice (one allocation, rune indices). Use range s unless you need random rune access or repeated passes.
Deep Dive & Architecture
The cost anatomy: range s — zero allocation, the decode is arithmetic per rune (the leading-bits width inference + a small lookup), total O(n) CPU. []rune(s) — the same decode walk PLUS an allocation (4 bytes per rune — 4x the string's byte count for ASCII input) plus the writes. The first pass over the slice is then pure iteration (cheaper per step than string decoding — the work was front-loaded). Break-even: one pass — string range wins (no alloc); many passes or indexed access — the slice wins (amortize the materialization).
The index-semantic difference, one layer down: string range's i is a byte offset — it's what slicing needs (s[i:] works immediately). []rune range's i is a rune index — it's what character arithmetic needs (rs[k:] gives the k-th character onward, not the k-th byte onward). The two 'indices' answer different questions, and picking the iteration form is really picking which index your logic needs.
The interop with the slice-tricks family: []rune materialization is what unlocks rune-level slice operations — reverse (swap ends), filter runes (even runes), dedupe characters. The byte equivalents corrupt multibyte runes (the reverse demonstration from the rune-vs-byte topic). The pattern: convert once, operate as a slice, convert back once — the batch-then-convert discipline, identical in shape to the Builder amortization.
Common Mistakes & Pitfalls
Repeating a definition without saying when to use it.
Check your understanding
Answer these without looking back at the article.
- What is String Iteration, and when would you use it?
- How would you compare String Iteration with an alternative?
- What is a common mistake when using String Iteration?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.