Beginner · Collections and structs · topic 13 of 46 · 35 min
Strings, bytes and runes
Explanation
Bytes, characters and UTF-8
Computers store text as numbers. UTF-8 is the standard way to turn any character from any language into bytes. English letters take 1 byte each, but ₹ takes 3 bytes and each Hindi letter like न also takes 3. A Go string is just those bytes, and Go source files are always UTF-8.
s := "₹500"
fmt.Println(len(s)) // 6 bytes (₹ is 3 bytes)
fmt.Println(utf8.RuneCountInString(s)) // 4 characters
fmt.Println(s[0]) // 226, the first BYTE, not "₹"
hi := "नमस्ते"
fmt.Println(len(hi), utf8.RuneCountInString(hi)) // 18 6A rune is Go's name for one Unicode code point (an int32). A rune literal uses single quotes: 'A', '₹'. Range over a string decodes the UTF-8 and gives you runes with their starting byte index.
for i, r := range "Go₹" {
fmt.Println(i, string(r))
}
// 0 G
// 1 o
// 2 ₹r := []rune("नमस्ते")
fmt.Println(len(r)) // 6
fmt.Println(string(r[0])) // न
b := []byte("hi")
fmt.Println(b) // [104 105]Strings cannot be changed
Strings are immutable: once made, their bytes never change. s[0] = 'X' is a compile error. To "change" a string you build a new one. This makes strings safe to share between goroutines.
Joining strings efficiently
name := "Asha"
msg := "Hello, " + name + "!" // fine for a few pieces
msg2 := fmt.Sprintf("%s has %d orders", name, 3)
var b strings.Builder
for i := 1; i <= 3; i++ {
fmt.Fprintf(&b, "Row %d;", i)
}
fmt.Println(b.String()) // Row 1;Row 2;Row 3;The strings package
| Function | Example | Result |
|---|---|---|
| strings.Contains | strings.Contains("Pune city", "city") | true |
| strings.HasPrefix | strings.HasPrefix("+91 98", "+91") | true |
| strings.Split | strings.Split("a,b,c", ",") | [a b c] |
| strings.Join | strings.Join([]string{"a", "b"}, "-") | a-b |
| strings.Fields | strings.Fields(" chai samosa ") | [chai samosa] |
| strings.TrimSpace | strings.TrimSpace(" hi \n") | hi |
| strings.ToUpper | strings.ToUpper("upi") | UPI |
| strings.ReplaceAll | strings.ReplaceAll("a-b-c", "-", "/") | a/b/c |
| strings.Repeat | strings.Repeat("*", 4) | **** |
| strings.EqualFold | strings.EqualFold("Go", "GO") | true (case-insensitive) |
Raw strings
A string in backticks is a raw string: backslashes are not escapes, and it can span several lines. It is handy for Windows paths, regular expressions, SQL queries and JSON samples.
path := `C:\Users\asha\notes.txt`
query := `
SELECT id, name
FROM students
WHERE marks > 80`
fmt.Println(path)Comparing strings
== compares the bytes exactly, so "Go" == "go" is false. < and > compare byte by byte (alphabetical order for plain English). Use strings.EqualFold for case-insensitive comparison of user input like email addresses.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Strings, bytes and runes · 1/7
Text in Go is stored in strings. Let us see what a string really holds.
Prefer a video by a teacher? Find free videos on “golang strings bytes runes utf8 strings package tutorial” on YouTube ↗
In real life: Masking a phone number on a receipt
Delivery and payment apps show only part of a phone number, like 98XXXXXX10, so a receipt photo does not leak it. The code trims spaces, removes a +91 prefix, checks there are 10 digits, and builds the masked text with strings.Repeat.
package main
import (
"fmt"
"strings"
)
func mask(phone string) string {
p := strings.TrimSpace(phone)
p = strings.TrimPrefix(p, "+91")
p = strings.ReplaceAll(p, " ", "")
if len(p) != 10 {
return "invalid"
}
return p[:2] + strings.Repeat("X", 6) + p[8:]
}
func main() {
fmt.Println(mask(" +91 98765 43210 ")) // 98XXXXXX10
fmt.Println(mask("12345")) // invalid
}Practice (0/4 done)
What does this print? fmt.Println(strings.ToUpper("upi") + "-" + strings.Repeat("9", 3))
What does len("₹10") return?
What does this print? parts := strings.Split("2025-08-15", "-") fmt.Println(len(parts), parts[1])
Write func initials(fullName string) string that returns the capital initials of a name, for example "asha rani kulkarni" gives "ARK". Ignore extra spaces.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Maps: key-value look-upsCollections and structs · same module
- Slices and stringsRust Programming · Borrowing, slices and lifetimes
- Strings and template literalsJavaScript Programming (language in depth) · Strings, decisions and loops
- Strings: methods, interpolation, verbatim and raw stringsC# and .NET · Arrays, strings and null
- Text: C strings and std::stringC++ Programming (modern C++ and DSA) · References, pointers, arrays and strings
- Strings: building, comparing and countingData Structures and Algorithms (DSA) for interviews · Arrays and strings
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What type do you get from s[0] when s is a string?
Answer: byte (uint8)
Indexing a string gives a single byte.
s := "hello"; s[0] = 'H'. What happens?
Answer: Compile error: strings are immutable
You cannot assign to a byte of a string. Build a new string instead.
Which is best for joining 10,000 pieces of text in a loop?
Answer: strings.Builder
Builder appends to one growing buffer instead of copying the whole string each time.
What does strings.Fields(" a b ") return?
Answer: [a b]
Fields splits on runs of white space and drops empty parts.
What is special about a string in backticks?
Answer: It is raw: no escape sequences and it can span lines
Raw string literals keep backslashes and newlines exactly as written.
What does len() return for a String?Related
What does 'a,b,,c'.split(',') give?Related
Answer: ['a', 'b', '', 'c']
Two commas in a row make an empty string between them.
What does immutable mean for strings?Related
Answer: Once made, a string's characters cannot change; methods return new strings
Every "change" creates a new string.
From Strings: methods, interpolation, verbatim and raw strings
What marks the end of a C string?Related
Answer: The null character '\0'
C functions read characters until they meet '\0'.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 2 more topics in “Collections and structs” before its exam: Maps: key-value look-ups, Structs and methods.
- Module 3 exam: Collections and structs · 15 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Pointers, interfaces and errors. 46 topics left in the course before the final exam.