0 day streak
go / intermediate
Snippet

Handling UTF-8 Text Correctly with Runes

In Go, strings are read-only slices of bytes. UTF-8 characters like emojis or accented letters occupy multiple bytes. Slicing or indexing a string directly accesses raw bytes, which can corrupt multi-byte characters. Go uses the rune type (an alias for int32) to represent a Unicode code point. A range loop over a string automatically decodes UTF-8 into runes, and casting a string to []rune allows correct character-based random access and length calculation.

snippet.go
go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main
import "fmt"
func main() {
text := "Gopher 🚀"
fmt.Println("Iterating by byte:")
for i := 0; i < len(text); i++ {
fmt.Printf("%x ", text[i])
}
fmt.Println()
fmt.Println("Iterating by rune (range loop):")
for index, runeVal := range text {
fmt.Printf("%d:%q ", index, runeVal)
}
fmt.Println()
runes := []rune(text)
fmt.Printf("Sub-string length: %d, Char at index 7: %c\n", len(runes), runes[7])
}
Breakdown
1
text := "Gopher 🚀"
Defines a string that contains standard ASCII characters and a multi-byte rocket emoji (which takes 4 bytes).
2
len(text)
Returns the length of the string in bytes (11 bytes), not the number of characters (8 characters).
3
for index, runeVal := range text
The range loop automatically decodes UTF-8 bytes into individual runes and provides their starting byte indices.
4
runes := []rune(text)
Converts the string into a slice of runes. This allocates memory but allows O(1) character-based indexing like runes[7].