debug a problem involving Rune Vs Byte
Fast recall
Quick revision
Core answer
Practical understanding of Rune Vs Byte.
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
[]rune(s) is the explicit decode — a fresh int32 slice holding every code point:
s := "héllo"
r := []rune(s) // [104 233 108 108 111] — one element per rune
r[1] // 233 — é, direct index
r[1] = 'E' // mutation works — it's a slice
s2 := string(r) // "hEllo" — re-encodeThe costs, always: O(n) decode to build, O(n) allocation for the slice, O(n) re-encode on the way back via string(). It's the bridge you pay for when you need SLICE OPERATIONS on characters.
When you need it — the honest list:
- 1Random rune access: r[i] — you want the i-th CHARACTER, repeatedly, without re-walking.
- 2Rune-level mutation: r[i] = 'X' — building modified strings by position.
- 3Rune-based algorithms: reversing a string's characters (swap r[i], r[len-1-i] — the byte version destroys multibyte runes), palindromes over characters, Caesar ciphers.
When you DON'T (the common waste): iteration — range gives each rune for free. Counting — RuneCountInString walks once without materializing a slice. One lookup — utf8.DecodeRuneInString or one range iteration, no slice.
debug a problem involving Rune Vs Byte
Direct Answer
Decodes the whole string into an int32 slice — every rune becomes an element, O(n) allocation. Need it for: random rune access by index, rune-level mutation, or rune-level algorithms. NOT for iteration (range is free).
Deep Dive & Architecture
The mechanics: []rune(s) runs the UTF-8 decoder over the string, appending each decoded code point to a growing int32 slice — same walk as range, but materializing the output (range discards each rune after the body). string(r) re-encodes each int32 to its UTF-8 bytes into a fresh string. Both directions are full passes with allocation — the bridge's toll.
Why the reverse-a-string idiom REQUIRES []rune — the classic demonstration: swapping bytes of "héllo" by index swaps the HALVES of é (195 and 169 become 169 and 195 — an invalid rune); the result isn't 'olléh' — it's corrupted bytes that decode to replacement characters. Swapping []rune elements moves the whole code point (233) as a unit — correct. Byte-reversal is only safe for known-ASCII inputs, and 'known-ASCII' is the assumption Unicode inputs violate.
The allocation profile interviewers care about: []rune in a LOOP is the same anti-pattern as string↔[]byte in a loop — each conversion allocates. The batch pattern: convert once, operate on the slice, convert back once — mirroring Builder's amortization. The advanced alternative for index-without-materialize: utf8.DecodeRuneInString(s[i:]) walks forward one rune at a time — zero allocation, but you manage the offset arithmetic yourself — the choice between 'readable and allocating' and 'manual and free.'
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 Rune Vs Byte, and when would you use it?
- When would you use Rune Vs Byte in a real project?
- What is a common mistake when using Rune Vs Byte?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.