ZetCode

Golang rune type

last modified May 8, 2025

This tutorial explains how to use the rune built-in type in Go. We'll cover Unicode handling with practical examples of text processing.

The rune type in Go is an alias for int32 and represents a Unicode code point. It's used to work with individual characters in UTF-8 encoded strings, which is Go's default string encoding.

In Go, rune provides proper support for international characters. Unlike bytes, runes can represent characters that require multiple bytes in UTF-8 encoding, such as non-ASCII characters.

Basic rune declaration and usage

The simplest way to use runes is to declare them as character literals. This example demonstrates basic rune operations and type conversion.
Note: Single quotes are used for rune literals in Go.

basic_rune.go
package main

import "fmt"

func main() {

    // Declaring rune variables
    var r1 rune = 'A'
    r2 := '€' // Euro symbol
    
    // Printing runes and their types
    fmt.Printf("r1: %c, type: %T\n", r1, r1)
    fmt.Printf("r2: %c, type: %T\n", r2, r2)
    
    // Converting between rune and integer
    codePoint := int(r2)
    fmt.Printf("Euro code point: %d\n", codePoint)
    
    // Converting back to rune
    r3 := rune(codePoint)
    fmt.Printf("Converted back: %c\n", r3)
}

The example shows rune declaration, printing with format verbs, and conversion between rune and integer types. The %c format verb displays the character.

Iterating over strings with runes

Strings in Go are UTF-8 encoded byte sequences. Using range on a string iterates over runes, not bytes. This example demonstrates proper string iteration.

string_iteration.go
package main

import "fmt"

func main() {

    s := "Hello, 世界"
    
    // Byte-by-byte iteration
    fmt.Println("Byte iteration:")
    for i := 0; i < len(s); i++ {
        fmt.Printf("%x ", s[i])
    }
    fmt.Println()
    
    // Rune-by-rune iteration
    fmt.Println("Rune iteration:")
    for idx, r := range s {
        fmt.Printf("%d: %c (U+%04X)\n", idx, r, r)
    }
    
    // Counting runes
    fmt.Printf("Length in bytes: %d\n", len(s))
    fmt.Printf("Length in runes: %d\n", len([]rune(s)))
}

The range loop properly handles multi-byte UTF-8 characters. The byte iteration shows raw bytes, while rune iteration shows proper Unicode characters.

Rune manipulation and functions

The unicode package provides functions for rune classification and transformation. This example demonstrates common rune operations.

rune_operations.go
package main

import (
    "fmt"
    "unicode"
)

func main() {

    runes := []rune{'A', 'ä', '3', ' ', '世', '\t'}
    
    for _, r := range runes {
        fmt.Printf("Rune: %c\n", r)
        fmt.Printf("  IsLetter: %t\n", unicode.IsLetter(r))
        fmt.Printf("  IsDigit: %t\n", unicode.IsDigit(r))
        fmt.Printf("  IsSpace: %t\n", unicode.IsSpace(r))
        fmt.Printf("  Lowercase: %c\n", unicode.ToLower(r))
        fmt.Printf("  Uppercase: %c\n", unicode.ToUpper(r))
        fmt.Println()
    }
}

The unicode package functions work with runes to provide character classification and case conversion. This is essential for proper text processing.

Building strings from runes

Runes can be converted to strings, either individually or as slices. This example shows string construction from rune values.

rune_to_string.go
package main

import "fmt"

func main() {

    // Single rune to string
    r := '😊'
    s1 := string(r)
    fmt.Println("Smile:", s1)
    
    // Rune slice to string
    runes := []rune{'H', 'e', 'l', 'l', 'o', ' ', '世', '界'}
    s2 := string(runes)
    fmt.Println("Greeting:", s2)
    
    // Modifying runes in a string
    msg := []rune("Hello World")
    msg[6] = 'G'
    msg[7] = 'o'
    msg[8] = 'l'
    msg[9] = 'a'
    msg[10] = 'ng'
    fmt.Println("Modified:", string(msg))
}

Converting between rune slices and strings is efficient in Go. This allows for easy string manipulation by working with rune slices.

Handling invalid UTF-8 with runes

When processing external data, invalid UTF-8 sequences may occur. This example shows how to handle such cases safely.

invalid_utf8.go
package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {

    // Contains invalid UTF-8 sequence
    data := []byte{0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x80, 0x80, 0xef, 0xbc, 0xa5}
    
    // Safe conversion with utf8.DecodeRune
    for len(data) > 0 {
        r, size := utf8.DecodeRune(data)
        if r == utf8.RuneError {
            fmt.Printf("Invalid UTF-8 sequence: %x\n", data[:size])
        } else {
            fmt.Printf("Valid rune: %c\n", r)
        }
        data = data[size:]
    }
    
    // Checking string validity
    str := string(data)
    if !utf8.ValidString(str) {
        fmt.Println("String contains invalid UTF-8")
    } else {
        fmt.Println("String is valid UTF-8")
    }
}

The utf8 package provides functions to safely handle potentially invalid UTF-8 data. This is crucial for robust text processing applications.

Source

Go language specification

This tutorial covered the rune type in Go with practical examples of Unicode text processing and manipulation.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Golang tutorials.