Skip to main content
Go Language Fundamentals for Beginners to Advanced
CHAPTER 12 Beginner

Strings and Runes

Updated: May 17, 2026
5 min read

# CHAPTER 12

Strings and Runes

1. Introduction

Handling text seems simple: text := "Hello". But what happens when your text contains emojis (😀), Japanese kanji (語), or Arabic script? Modern backend systems must handle global data flawlessly. Go was created by the same engineers who invented the UTF-8 encoding standard, making Go's approach to strings uniquely powerful, but slightly different from older languages.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Understand that a String is an immutable slice of Bytes.
  • Understand the difference between a Byte and a Rune.
  • Use the strings package for manipulation.
  • Iterate over strings safely without breaking multi-byte characters.

3. Strings are Immutable Byte Slices

In Go, a string is simply a read-only (immutable) slice of bytes (uint8). Once a string is created, its contents cannot be changed.
go
123456789
package main
import "fmt"

func main() {
    name := "Golang"
    // name[0] = 'B' // ERROR! Strings are read-only.
    
    fmt.Println(name)
}

4. The Problem with Bytes (UTF-8)

In the old ASCII system, every character was exactly 1 byte. 'A' is 1 byte. In modern UTF-8, an English letter is 1 byte, but an emoji or Chinese character might take 3 or 4 bytes!

If you use len() on a string, it returns the number of bytes, NOT the number of human-readable characters!

go
12345678
func main() {
    word := "Hello"
    fmt.Println(len(word)) // Prints 5 (5 characters, 5 bytes)

    emoji := "Hello 世界" // "World" in Chinese
    // 'Hello ' is 6 bytes. '世' is 3 bytes. '界' is 3 bytes.
    fmt.Println(len(emoji)) // Prints 12 bytes! Not 8 characters!
}

5. Enter the rune

To solve this, Go introduced the rune data type. A rune is an alias for int32. It holds the exact Unicode value of a character, regardless of whether it takes 1 byte or 4 bytes.

If you want to count the actual human-readable characters, you convert the string to a slice of runes, or use the utf8 package.

go
123456789
import "unicode/utf8"

func main() {
    emoji := "Hello 世界"
    
    // Correct way to count characters
    charCount := utf8.RuneCountInString(emoji)
    fmt.Println("Total characters:", charCount) // Prints 8
}

6. Single Quotes vs Double Quotes

  • Double Quotes (" "): Used for Strings. "A" is a string.
  • Single Quotes (' '): Used for Runes. 'A' is a rune (it actually represents the number 65, its Unicode value).

7. The strings Package

Go provides a robust standard library for string manipulation. *(Requires import "strings")*
go
12345678910111213141516171819202122
import (
    "fmt"
    "strings"
)

func main() {
    text := "   Go is Awesome!   "

    // 1. ToUpper / ToLower
    fmt.Println(strings.ToUpper(text))

    // 2. TrimSpace (Removes leading/trailing spaces)
    cleanText := strings.TrimSpace(text)

    // 3. Contains (Checks for a substring)
    hasGo := strings.Contains(cleanText, "Go") // true

    // 4. ReplaceAll
    newText := strings.ReplaceAll(cleanText, "Awesome", "Fast")
    
    fmt.Println(newText) // "Go is Fast!"
}

8. Common Mistakes

  • Indexing a multi-byte string: If you do char := emoji[6], you are grabbing the first byte of a 3-byte Chinese character. It will print random garbage. Always convert the string to a []rune if you need to access specific characters by index.
  • String Concatenation in Loops: Strings are immutable. text += "a" creates a brand new string in memory every time. Doing this 10,000 times causes massive memory lag. Use strings.Builder for heavy string generation.

9. Best Practices

  • Use for index, char := range myString to iterate over strings. The range keyword is smart enough to automatically decode UTF-8 bytes into whole Runes!

10. Exercises

  1. 1. Write a program that defines word := "Golang".
  1. 2. Use the strings package to print whether it contains the substring "go" (Hint: Make sure to handle case-sensitivity!).

11. MCQs with Answers & Explanations

Question 1

In Go, what is a string fundamentally made of?

Q2. Can you modify a specific character in a string directly (e.g., text[0] = 'A')? a) Yes b) No, strings are immutable Answer: b) No, strings are immutable.
Question 3

What does len("Hello 😀") return?

Question 4

What is a rune in Go?

Question 5

How do you properly find the number of human-readable characters in a string containing emojis?

Question 6

What does "A" (double quotes) represent?

Question 7

What does 'A' (single quotes) represent?

Question 8

Which package provides functions like ToUpper, Contains, and ReplaceAll?

Question 9

If you loop over a string using for ... range, what does the loop automatically yield?

Question 10

For high-performance string building inside a large loop, what should you use?

12. Interview Preparation

Interview Questions:
  1. 1. Explain the difference between len("Golang") and len("世界").
  1. 2. Differentiate between a byte, a rune, and a string in Go.

13. Summary

Go's text handling is deeply tied to the UTF-8 standard. By understanding that strings are just immutable slices of bytes, and that characters (runes) can be of variable width, you avoid the encoding bugs that plague older languages. The strings and utf8 packages provide all the tools needed for robust text manipulation.

14. Next Chapter Recommendation

We have referenced "Memory Addresses" and "Pointers" several times. In Chapter 13: Pointers in Go, we will demystify exactly what a pointer is and why it is the secret to Go's extreme performance.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·