Strings & Runes

UTF-8 strings, byte vs rune iteration, string manipulation, and the strings package.

Beginner 25 min read 🐹 Go

String Basics

Go strings are immutable sequences of bytes, typically UTF-8 encoded. A string is essentially a read-only []byte with a length. This means indexing a string gives you a byte, not a character.

s := "Hello, World!"

fmt.Println(len(s))    // 13 (bytes, not characters)
fmt.Println(s[0])      // 72 (byte value of 'H')
fmt.Printf("%c\n", s[0]) // H (as character)

// Strings are immutable
// s[0] = 'h'  // compile error!

Runes — Unicode Characters

A rune is an alias for int32 and represents a Unicode code point. For ASCII, one byte = one rune. But multi-byte characters (emoji, Chinese, etc.) use multiple bytes for one rune.

s := "Hello, 你好!"

fmt.Println(len(s))           // 14 (bytes)
fmt.Println(len([]rune(s)))   // 9 (characters/runes)

// range iterates RUNES, not bytes (correct!)
for i, ch := range s {
    fmt.Printf("%d: %c (U+%04X)\n", i, ch, ch)
}
Key Takeaway: Use range to iterate over strings — it correctly handles multi-byte UTF-8 characters. Use len([]rune(s)) for character count, len(s) for byte count.

The strings Package

import "strings"

s := "  Hello, World!  "

fmt.Println(strings.TrimSpace(s))           // "Hello, World!"
fmt.Println(strings.ToUpper("hello"))       // "HELLO"
fmt.Println(strings.Contains(s, "World"))   // true
fmt.Println(strings.Replace(s, "World", "Go", 1))
fmt.Println(strings.Split("a,b,c", ","))    // [a b c]
fmt.Println(strings.Join([]string{"a","b"}, "-")) // "a-b"
fmt.Println(strings.HasPrefix("golang", "go"))    // true

Efficient String Building

// Bad: string concatenation in loop (O(n^2))
// s := ""
// for _, word := range words { s += word + " " }

// Good: strings.Builder (O(n))
var b strings.Builder
for _, word := range []string{"Hello", "from", "Go"} {
    b.WriteString(word)
    b.WriteByte(' ')
}
fmt.Println(b.String()) // "Hello from Go "

⚠️ Common Mistake: String concatenation in loops

Strings are immutable. Each += creates a new string and copies all previous bytes. For n words, this is O(n²). Use strings.Builder or strings.Join() instead.

Practice Exercises

Easy Hello World Variant

Modify the example to accept user input and print a personalized greeting.

Easy Code Reading

Read through the code examples above and predict the output before running them.

Medium Extend the Example

Take one code example and add error handling, input validation, or a new feature.