Strings in Go
By Syncfusion®, Inc. · Last updated
Create interpreted and raw strings, find the length, join, slice and compare text, use the strings package, understand runes, Unicode and UTF-8, and build text with strings.Builder.
What Are Strings?
String = a piece of text, like a name, a sentence or a roll number.
- In Go, a string is written in double quotes:
"Asha". - Inside, a string is a row of bytes.
- A string cannot be changed once it is made. You make a new string instead.
Immutable = cannot be changed after it is made.
Simple lesson: a string is text, stored as bytes, and it never changes in place.
A Real-World Example
The school office prints ID cards.
- The clerk joins first and last names:
"Asha" + " " + "Rao". - She trims extra spaces someone typed by mistake.
- She makes the name CAPITAL for the card.
- She checks if the email contains
@.
Every one of these jobs is a string operation.
Go's strings package has a ready-made function for each.
You met the string type in Data Types.
This lesson shows how to work with strings: join, compare, search, split, change and build them.
What You Will Learn
In this lesson, you will learn:
- How to create strings, and the two kinds of string literals.
- How to find the length, join and compare strings.
- The most useful functions in the
stringspackage. - How runes, Unicode and UTF-8 work, and why
lencounts bytes. - How to build long strings fast with
strings.Builder.
String Fundamentals
Creating Strings
Ways to make a string
package main
import "fmt"
func main() {
var school string = "Green Valley School"
city := "Pune"
var empty string
fmt.Println(school, city)
fmt.Printf("%q\n", empty)
}
Green Valley School Pune
""
- The zero value of a string is
"", the empty string.
Interpreted Strings
Interpreted string = text in double quotes " ". Go understands escape sequences inside it.
Escape sequence = a backslash \ plus a letter, for a special character.
| Escape | Means |
|---|---|
\n | new line |
\t | tab (a wide space) |
\" | a double quote inside the text |
\\ | one backslash |
Escape sequences
package main
import "fmt"
func main() {
fmt.Println("Name:\tAsha\nClass:\t8A")
fmt.Println("She said \"Good morning!\"")
}
Name: Asha
Class: 8A
She said "Good morning!"
Raw Strings
Raw string = text in back-quotes ` `. Go keeps every character exactly as typed.
- No escape sequences:
\nstays as two characters. - It can go over many lines.
- Great for file paths, poems and blocks of text.
A raw string
package main
import "fmt"
func main() {
path := `C:\school\new\marks.txt`
poem := `Roses are red,
Go is quite neat.`
fmt.Println(path)
fmt.Println(poem)
}
C:\school\new\marks.txt
Roses are red,
Go is quite neat.
Interpreted vs raw
Simple lesson: use " " for normal text with escapes, and back-quotes for text kept exactly as typed.
String Operations
Length
len counts bytes
package main
import "fmt"
func main() {
fmt.Println(len("Ravi"))
fmt.Println(len("Ravi Kumar"))
fmt.Println(len(""))
}
4
10
0
len()counts bytes, and a space is a byte too.- For English letters, one letter is one byte. See Runes and Unicode for other languages.
Concatenation
Concatenation = joining strings end to end with +.
Join strings
package main
import "fmt"
func main() {
first, last := "Asha", "Rao"
full := first + " " + last
full += ", Class 8A"
fmt.Println(full)
}
Asha Rao, Class 8A
+=adds text to the end. It actually makes a new string.- To join a number, convert it first:
"Roll " + strconv.Itoa(7). See Data Types.
Indexing and Slicing
s[i]gives the byte at positioni, starting at 0.s[a:b]gives the text from positionaup to, but not including,b.
Pick parts of a string
package main
import "fmt"
func main() {
code := "GVS-2025-8A"
fmt.Println(code[0], string(code[0]))
fmt.Println(code[:3])
fmt.Println(code[4:8])
fmt.Println(code[9:])
}
71 G
GVS
2025
8A
code[0]is a byte, so it prints as the number71.code[:3]means "from the start to 3".code[9:]means "from 9 to the end".- You cannot change a byte:
code[0] = 'X'does not build.
Comparison
Compare strings
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println("Asha" == "Asha")
fmt.Println("Asha" == "asha")
fmt.Println("apple" < "banana")
fmt.Println(strings.EqualFold("GO", "go"))
}
true
false
true
true
==and!=check for the exact same text. Capital letters matter.<and>compare in dictionary order, byte by byte.strings.EqualFoldcompares and ignores capital letters.
Simple lesson: len counts bytes, + joins, [a:b] cuts out a part, and == compares exactly.
String Functions
The strings package has many ready-made functions.
Click each tab to see one group.
The strings package, by job
Contains
Search in text
package main
import (
"fmt"
"strings"
)
func main() {
email := "asha.rao@gvs.edu"
fmt.Println(strings.Contains(email, "@"))
fmt.Println(strings.HasSuffix(email, ".edu"))
fmt.Println(strings.Index(email, "@"))
fmt.Println(strings.Index(email, "#"))
}
true
true
8
-1
Indexgives the position where the text starts.-1means "not found".
Split and Join
Split a CSV line, then join it back
package main
import (
"fmt"
"strings"
)
func main() {
line := "Asha,8A,91"
parts := strings.Split(line, ",")
fmt.Println(parts, len(parts))
fmt.Println(parts[0], "is in", parts[1])
fmt.Println(strings.Join(parts, " | "))
}
[Asha 8A 91] 3
Asha is in 8A
Asha | 8A | 91
Splitgives a slice of strings. You will learn slices in Slices.Joinis the opposite ofSplit.
Replace
Replace text
package main
import (
"fmt"
"strings"
)
func main() {
notice := "Holiday on Monday. Monday classes move to Saturday."
fmt.Println(strings.Replace(notice, "Monday", "Friday", 1))
fmt.Println(strings.ReplaceAll(notice, "Monday", "Friday"))
}
Holiday on Friday. Monday classes move to Saturday.
Holiday on Friday. Friday classes move to Saturday.
- The last number in
Replaceis how many to change.-1means all. ReplaceAllchanges every match.
Trim, ToUpper and ToLower
Clean up a name for an ID card
package main
import (
"fmt"
"strings"
)
func main() {
typed := " kavya sharma \n"
clean := strings.TrimSpace(typed)
fmt.Printf("%q\n", clean)
fmt.Println(strings.ToUpper(clean))
fmt.Println(strings.ToLower("GVS"))
fmt.Println(strings.Trim("***TOPPER***", "*"))
}
"kavya sharma"
KAVYA SHARMA
gvs
TOPPER
TrimSpaceremoves spaces, tabs and new lines at both ends only.- The spaces in the middle stay.
Simple lesson: the strings package can search, split, join, replace, trim and change case, always returning a new string.
Runes and Unicode
Unicode Characters
Unicode = one big list that gives every character in every language a number.
Ais 65.अis 2309.😀is 128512.
Rune = one Unicode character in Go. It is an int32. See Data Types.
UTF-8
UTF-8 = the way Go stores Unicode characters as bytes.
- English letters take 1 byte.
- Hindi, Tamil and most Indian scripts take 3 bytes per character.
- Emoji take 4 bytes.
Type some text and watch the bytes.
Compare the two numbers:
lencounts bytes.RuneCountInStringcounts characters.
Bytes vs characters
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
word := "नमस्ते"
fmt.Println(len(word))
fmt.Println(utf8.RuneCountInString(word))
letters := []rune(word)
fmt.Println(string(letters[0]))
}
18
6
न
[]rune(word)turns the text into a list of characters.- Then
letters[0]is the first character, not the first byte.
range Over a String
range walks through a string one rune at a time.
range gives runes
package main
import "fmt"
func main() {
for i, r := range "Go₹" {
fmt.Println(i, string(r))
}
}
0 G
1 o
2 ₹
₹uses 3 bytes, so if there were a next character, it would start at position 5.rangehandles that for you.
s[i] gives a byte, not a character.
For text that may not be English, use range or []rune(s).
Simple lesson: Go stores text as UTF-8 bytes, so use runes when you mean characters.
String Builder
strings.Builder
Every + makes a brand-new string.
In a big loop, that wastes time and memory.
strings.Builder = a tool that collects text piece by piece, and makes the final string once.
Press Play to watch a builder fill up.
Build a roll list
var b strings.Builderis ready to use. No set-up needed.b.WriteString(s)adds text.fmt.Fprintf(&b, ...)adds formatted text. The&is explained in Pointers.b.String()gives the result.
A report line with a Builder
package main
import (
"fmt"
"strings"
)
func main() {
marks := []int{91, 78, 85}
var b strings.Builder
b.WriteString("Marks: ")
for i, m := range marks {
if i > 0 {
b.WriteString(", ")
}
fmt.Fprintf(&b, "%d", m)
}
fmt.Println(b.String())
}
Marks: 91, 78, 85
Easy way to remember
- A few joins:
+is fine. - A loop of joins: use
strings.Builder. - A list to join:
strings.Join.
Simple lesson: use strings.Builder to build a long string piece by piece.
TL;DR
String = immutable text, stored as UTF-8 bytes.
- Interpreted =
"...", with\n,\t,\". - Raw = back-quotes, kept exactly, can span lines.
- Interpreted =
- Length =
len(s), in bytes. Join =+. Part =s[a:b]. - Compare =
==,<, orstrings.EqualFoldto ignore case. - strings package =
Contains,Index,Split,Join,Replace,ReplaceAll,Trim,TrimSpace,ToUpper,ToLower,Repeat,Fields. Rune = one character. UTF-8 = 1 to 4 bytes per character.
utf8.RuneCountInString(s)= number of characters.rangeover a string gives runes.
- strings.Builder = build long text fast:
WriteString, thenString().
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
s[0] = 'X' | Strings can be changed in place | Strings are immutable | A build error. Make a new string. |
len("नमस्ते") for the letter count | len counts characters | len counts bytes | You get 18, not 6. |
s[0] to get the first letter of Hindi text | Each index is a character | Each index is a byte | A broken character. Use []rune(s). |
"Roll " + 7 | + joins any value | Convert numbers first | mismatched types |
strings.Replace(s, a, b) | It replaces all by default | It needs a count. Use ReplaceAll | A build error (missing argument). |
strings.ToUpper(s) without using the result | It changes s | It returns a new string | s stays the same. |
+= in a big loop | It is free | Each + copies the string | Slow programs. Use strings.Builder. |
Check Yourself
Exercises
What to Remember
- A string is immutable text, stored as UTF-8 bytes.
"..."understands\nand\t. Back-quotes keep text exactly.lencounts bytes. Useutf8.RuneCountInStringor[]runefor characters.stringsfunctions return a new string. Store the result.SplitandJointurn text into a list and back.- Use
strings.Builderto build long text in a loop.
Next: Time and Date. You will learn how to work with dates, times and durations in Go.