Skip to content

Go Strings and Runes

In Go, strings are read-only slices of bytes. When we talk about "characters," Go uses a concept called a rune.

What is a Rune?

A rune is an alias for int32. It represents a single Unicode character (code point). Since some characters (like '世' or emojis) take up multiple bytes, a simple index like s[i] might only give you a fraction of a character.

Basic Example

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    // A string with a multi-byte character
    const s = "Hello, 世界"

    // len() returns the number of BYTES
    fmt.Println("Len:", len(s)) // 13

    // RuneCountInString returns the number of CHARACTERS
    fmt.Println("Rune count:", utf8.RuneCountInString(s)) // 9

    // To access characters correctly, we use a range loop
    for i, runeValue := range s {
        fmt.Printf("%#U starts at byte position %d\n", runeValue, i)
    }
}

Key Differences

Feature String Byte (s[i]) Rune (rune)
Represents A single byte (8 bits) A Unicode character (32 bits)
Best for Raw data, ASCII text International text, Emojis

String Operations

Go provides a powerful strings package for common tasks:

package main

import (
    "fmt"
    "strings"
)

func main() {
    s := "test"

    fmt.Println(strings.Contains(s, "es")) // true
    fmt.Println(strings.Count(s, "t"))    // 2
    fmt.Println(strings.HasPrefix(s, "te")) // true
    fmt.Println(strings.ToUpper(s))         // TEST
}

Important Rule: Immutability

Strings in Go are immutable. You cannot change a character inside a string once it is created.

s := "hello"
// s[0] = 'H' // This will cause an error

To modify a string, you must convert it to a slice of runes or bytes, change it, and convert it back:

1
2
3
runes := []rune(s)
runes[0] = 'H'
s = string(runes) // "Hello"