← Back to Go Course | Chapter 2: Variables & Types | Lesson 7 of 7

Strings and Runes

A Go string is a row of bytes, but a rune is one whole character (even fancy ones like emoji), so Go gives you both views when you need to work with real-world text.

Strings Are Byte Sequences

A Go string is fundamentally an immutable sequence of bytes. For plain ASCII text each byte is one character, but for Unicode text (like emoji or non-Latin scripts) a single character can be encoded as multiple bytes using UTF-8.

Example: Strings Are Byte Sequences

markup
package main

import "fmt"

func main() {
	s := "Go"
	fmt.Println("bytes:", len(s))
	fmt.Println("first byte:", s[0])
}

What Is a Rune?

A rune represents one Unicode code point -- one real, human-perceived character -- regardless of how many bytes it takes to encode in UTF-8. Converting a string to []rune gives you a slice where each element is exactly one character.

Note: rune is just an alias for int32 in Go.

Example: What Is a Rune?

markup
package main

import "fmt"

func main() {
	s := "café"
	fmt.Println("byte length:", len(s))
	fmt.Println("rune length:", len([]rune(s)))
}

Iterating Correctly with for range

Using 'for range' on a string automatically decodes it rune by rune, giving you the correct starting byte index and the full Unicode code point at each step, which correctly handles multi-byte characters instead of splitting them apart.

Note: Never loop with a plain byte index if the string might contain non-ASCII characters.

Example: Iterating Correctly with for range

markup
package main

import "fmt"

func main() {
	for i, r := range "café" {
		fmt.Printf("index %d: %c\n", i, r)
	}
}

Strings Are Immutable

Once created, a Go string's contents can never be changed in place -- operations that appear to modify a string, like concatenation, actually produce a brand-new string. To build up text piece by piece efficiently, Go provides strings.Builder.

Example: Strings Are Immutable

markup
package main

import "fmt"

func main() {
	s := "Hello"
	s = s + ", Go!" // creates a new string, doesn't mutate the old one
	fmt.Println(s)
}
Common Mistakes
  1. Indexing a string with s[i] expecting a character, when it actually returns a single byte, breaking on multi-byte Unicode characters.
  2. Using len(s) to count characters when the string contains multi-byte UTF-8 characters -- len returns byte count, not character count.
  3. Trying to modify a string in place, e.g. s[0] = H, which fails because strings are immutable in Go.
Chapter Summary
  • Go strings are immutable sequences of bytes, usually holding UTF-8 encoded text.
  • A rune represents a single Unicode code point (one real character), stored as an int32.
  • 'for range' over a string iterates rune by rune, correctly handling multi-byte characters.
  • len(s) returns the byte count, not the character count, for non-ASCII strings.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.