JuniorCodeOccasionalNot answered yet
What does len(s) versus utf8.RuneCountInString(s) print for s := "héllo"?
Read the snippet below. The string "héllo" contains the multi-byte UTF-8 character é.
Determine what len(s) and utf8.RuneCountInString(s) each print, and explain why the two numbers differ.
import "unicode/utf8"
s := "héllo"
fmt.Println(len(s), utf8.RuneCountInString(s))
Predict the output.
It prints 6 5. len(s) counts bytes, and é is two bytes in UTF-8, so the byte length is 6 while the rune (character) count is 5. Ranging with for i, r := range s iterates runes, while indexing s[i] yields a single byte, not a character.
- ✗Assuming
len(s)returns the character count — it returns the byte count - ✗Thinking
s[i]indexes runes; it indexes bytes - ✗Forgetting multi-byte UTF-8 characters like
éoccupy more than one byte
- →How many iterations does
for i, r := range sperform, and what isiafter theé? - →Why does
[]rune(s)allocate whilerangeover the string does not?
Contents
What does this code print?
import "unicode/utf8"
s := "héllo"
fmt.Println(len(s), utf8.RuneCountInString(s))
Output
6 5
Bytes versus runes
A Go string is an immutable sequence of bytes encoded as UTF-8, not a sequence of characters.
len(s)returns the byte count. The Latiné(U+00E9) takes two bytes in UTF-8 (0xC3 0xA9), whileh,l,l,otake one each. Total2 + 1*4 = 6.utf8.RuneCountInString(s)decodes the bytes into runes (code points) and counts them:h é l l o=5.
Two consequences when working with strings:
for i, r := range s { /* r is a rune, i is the byte index of the rune start */ }
b := s[1] // byte 0xC3 — half of 'é', NOT a character
⚠️ Indexing s[i] yields a byte; to work with characters, iterate with range or convert to []rune(s) (which allocates).
Contents