a common mistake when using 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
Indexing is bytes because that's the only O(1) possibility. A string is bytes; rune boundaries are only discoverable by walking from the start. s[i] answers 'what byte is at position i' — always O(1), always a uint8:
s := "héllo"
s[0] // 104 — 'h'
s[1] // 195 — first byte of é's TWO-byte encoding
s[2] // 169 — second byte — meaningless as a 'character'Executed. s[1] and s[2] are halves of one rune — blind indexing can hand you a byte that isn't a character at all.
Getting a rune, with the cost stated:
r := []rune(s)[1] // 233 — é, after an O(n) conversion[]rune(s) decodes the whole string once into an int32 slice — then indexing is O(1). For one-off lookups it's the tool; in a loop it's a per-iteration allocation (range decodes for free).
The design defense: Go chose the cheap honest primitive (byte access, O(1)) over the expensive convenient one (rune access, O(n) hidden behind s[i]). Character logic is opt-in; byte logic is free. ASCII-only programs never pay; Unicode programs say so out loud.
a common mistake when using Rune Vs Byte
Direct Answer
s[i] is the i-th BYTE of the UTF-8 encoding (uint8). Characters are variable width — no O(1) 'character at index' exists in UTF-8. The language gives you the byte honestly; runes are opt-in ([]rune, range, utf8).
Deep Dive & Architecture
Why random rune access can't be O(1): UTF-8 code points are variable width, so rune #k's position depends on total widths of runes #0..#k-1 — unknowable without walking. A 'rune index' would either hide an O(n) walk behind s[i] (surprising) or need a parallel index per string (bloating the two-word header). Go chose honest bytes.
The contrast with fixed-width indexing: Java's char (UTF-16, 2 bytes) gave O(1) indexing — until Unicode outgrew 16 bits and surrogate pairs reintroduced variable width (supplementary characters occupy 2 chars — charAt lies about them; the 'fix' is codePointAt with its own semantics). The lesson: variable width is the truth of Unicode; fixed-width was an approximation that broke. Go's byte index never lies; its rune story (range) was correct from day one.
[]rune as the bridge, mechanically: it materializes the parallel structure (an int32 slice — random rune access, O(1), after the one O(n) conversion). Both access patterns at their true costs, and the conversion is the explicit bridge where you pay for random access.
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?
- How would you compare Rune Vs Byte with an alternative?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.