Runes vs Bytes
Understand Go string internals.
Runes vs Bytes is a free Go Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Go Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Is a Go String?
In Go a string is an immutable sequence of bytes. The bytes usually hold UTF-8 encoded text, but Go never forces that.
- You cannot change a string in place.
- Its
lencounts bytes, not characters.
package main
import "fmt"
func main() {
s := "Go"
fmt.Println(s)
fmt.Println(len(s))
}Bytes Behind the Scenes
Indexing a string with s[i] returns a single byte (type byte, an alias for uint8).
For plain ASCII text each character is exactly one byte.
package main
import "fmt"
func main() {
s := "ABC"
fmt.Println(s[0])
fmt.Println(s[1])
fmt.Println(s[2])
}A byte Is a Number
Because a byte is just a number, printing s[0] shows 65 (the ASCII code for A), not the letter.
To see the character, convert the byte back to a string.
package main
import "fmt"
func main() {
s := "ABC"
fmt.Println(string(s[0]))
}What Is a rune?
A rune is an alias for int32 and represents a single Unicode code point.
- One rune can span multiple bytes when encoded as UTF-8.
- Use runes when you care about characters, not raw bytes.
package main
import "fmt"
func main() {
var r rune = 'A'
fmt.Println(r)
fmt.Println(string(r))
}Multibyte Characters
Non-ASCII characters take more than one byte in UTF-8. A string like "héllo" has more bytes than letters.
Notice how len reports the byte count, which is larger than the visible length.
package main
import "fmt"
func main() {
s := "héllo"
fmt.Println(len(s))
}Ranging Over a String
A for range loop over a string decodes UTF-8 automatically. Each iteration yields:
- the byte index where the rune starts,
- the rune itself.
package main
import "fmt"
func main() {
for i, r := range "héllo" {
fmt.Println(i, string(r))
}
}Counting Characters Correctly
To count characters instead of bytes, convert the string to a []rune and take its length.
This gives the number of code points.
package main
import "fmt"
func main() {
s := "héllo"
runes := []rune(s)
fmt.Println(len(runes))
}Indexing by Rune
Once you have a []rune, you can index it to get the Nth character reliably, even with multibyte text.
package main
import "fmt"
func main() {
runes := []rune("héllo")
fmt.Println(string(runes[1]))
}Strings to Bytes and Back
You can convert freely between a string and a []byte.
[]byte(s)gives the raw bytes.string(b)rebuilds the text.
package main
import "fmt"
func main() {
b := []byte("Go")
fmt.Println(b)
fmt.Println(string(b))
}Building a String from Runes
A slice of runes converts back into a string the same way. This is handy after editing characters individually.
package main
import "fmt"
func main() {
runes := []rune{'G', 'o', '!'}
fmt.Println(string(runes))
}Bytes vs Runes Summary
Quick mental model:
byte= one raw byte (uint8),len(s)counts these.rune= one Unicode code point (int32),rangeyields these.- Use
[]runewhen counting or indexing characters.
package main
import "fmt"
func main() {
s := "café"
fmt.Println(len(s))
fmt.Println(len([]rune(s)))
}Quick Check
Test your understanding of runes and bytes.
Recap: Runes vs Bytes
You learned that Go strings are immutable byte sequences, usually UTF-8.
byteis a raw byte;lencounts bytes.runeis a Unicode code point;rangedecodes them.- Convert with
[]byte(s)and[]rune(s)to work at the right level.
package main
import "fmt"
func main() {
s := "Go語"
fmt.Println("bytes:", len(s))
fmt.Println("runes:", len([]rune(s)))
}Frequently asked questions
Is the “Runes vs Bytes” lesson free?
Yes — the full text of “Runes vs Bytes” is free to read here on the web, and the Go Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Go Academy course, upgrade to CoddyKit PRO.
What will I learn in “Runes vs Bytes”?
Understand Go string internals. You practise Go Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Go Academy?
No prior experience is required. Go Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Runes vs Bytes” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Go Academy lesson?
Yes. Every Go Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Runes vs Bytes
- strings Package Functions
- strings.Builder
- Unicode and utf8