String Indexing Returns Bytes Not Runes

unexpected byte value when indexing string with Unicode characters

Quick Answer

Indexing a string with s[i] returns a byte, not a rune. Use a for range loop or convert to []rune for Unicode-safe character access.

Why This Happens

Go strings are byte sequences, not character sequences. Indexing a string returns a byte, which may be only part of a multi-byte Unicode character. For range loops over strings yield runes (full Unicode code points), which is usually what you want for text processing.

The Problem

func main() {
    s := "Hello, \u4e16\u754c"
    fmt.Println(len(s))    // 13 (bytes, not characters)
    fmt.Println(s[7])      // 228 (first byte of a 3-byte rune)
}

The Fix

func main() {
    s := "Hello, \u4e16\u754c"
    runes := []rune(s)
    fmt.Println(len(runes)) // 9 (characters)
    fmt.Println(string(runes[7])) // prints correct character
}

Step-by-Step Fix

  1. 1

    Identify byte vs rune access

    Check if your code indexes strings directly when it should handle Unicode characters.

  2. 2

    Use range for iteration

    for i, r := range s gives you the rune and its byte offset.

  3. 3

    Convert to []rune for indexing

    If you need random access to characters, convert the string to []rune first.

Bugsly catches this automatically

Bugsly's AI analyzes this error pattern in real-time, explains what went wrong in plain English, and suggests the exact fix — before your users even report it.

Try Bugsly free