Runes in Golang
If you prepare for Go interviews, you must understand rune.
Many string problems look easy at first, but they break when the input contains Unicode characters such as a, Z, ä½ , 界, or 🙂.
That is where rune becomes important.
What is a rune in Go?
In Go, a rune is an alias for int32.
It represents a Unicode code point.
That means a rune can store values such as:
'A''z''ä½ ''界'
Example:
package main
import "fmt"
func main() {
var ch rune = '界'
fmt.Printf("%c %T %d\n", ch, ch, ch)
}
Output:
界 int32 30028
Here:
%cprints the character%Tprints the type%dprints the Unicode code point as an integer
Why interviewers ask about runes
Interviewers ask about rune because many candidates assume that:
- one string index means one character
len(s)means number of characters- reversing a string by bytes is always safe
All of these assumptions can be wrong in Go.
If the string contains only plain ASCII characters, byte-based code may work.
If the string contains multi-byte Unicode characters, the same code may fail.
Difference between byte and rune
This is the most important distinction:
byteis an alias foruint8runeis an alias forint32byteusually represents raw data or one UTF-8 byterunerepresents one Unicode code point
Example:
package main
import "fmt"
func main() {
s := "Goè¯è¨€"
fmt.Println("len(s):", len(s))
fmt.Println("len([]rune(s)):", len([]rune(s)))
}
Output:
len(s): 8
len([]rune(s)): 4
Why?
Gtakes 1 byteotakes 1 byteè¯takes 3 bytes in UTF-8言takes 3 bytes in UTF-8
So the string has:
8bytes4runes
Important fact about strings in Go
A Go string is a read-only sequence of bytes.
So:
len(s)returns number of bytess[i]returns a byte, not a rune
Example:
package main
import "fmt"
func main() {
s := "界"
fmt.Println(len(s))
fmt.Println(s[0])
}
Output:
3
231
The output is 3 because 界 takes 3 bytes in UTF-8.
The value 231 is only the first byte of that character, not the full character.
This is the reason many interview solutions fail for Unicode input.
How to iterate over runes correctly
Use a for range loop when you want to process characters safely.
Example:
package main
import "fmt"
func main() {
s := "Go界"
for i, r := range s {
fmt.Printf("byte index: %d, rune: %c, code point: %d\n", i, r, r)
}
}
Output:
byte index: 0, rune: G, code point: 71
byte index: 1, rune: o, code point: 111
byte index: 2, rune: 界, code point: 30028
Notice that:
iis the byte indexris the rune value
This is a very common interview detail.
Many candidates think i is the character position, but it is actually the byte position in the original string.
How to index by character position
If you want to access the 3rd character, convert the string to []rune first.
Example:
package main
import "fmt"
func main() {
s := "Goè¯è¨€"
runes := []rune(s)
fmt.Printf("%c\n", runes[2])
}
Output:
è¯
This is the correct approach when an interview problem says:
- get the
kth character - reverse the string
- compare characters from left and right
- build a frequency map by character
Converting between string and rune slice
You will often use these two conversions:
runes := []rune(s)
s2 := string(runes)
This is useful when you need to modify characters, because strings in Go are immutable.
Example:
package main
import "fmt"
func main() {
s := "cat"
runes := []rune(s)
runes[0] = 'b'
fmt.Println(string(runes))
}
Output:
bat
Rune literals
Single quotes represent rune literals in Go.
Examples:
var a rune = 'A'
var b rune = 'ä½ '
var newline rune = '\n'
Do not confuse:
'A'-> rune"A"-> string
Common interview problems where runes matter
Runes are especially important in problems involving:
- string reversal
- palindrome checking
- frequency counting
- sliding window over characters
- anagram detection
- first non-repeating character
- string compression or transformation
If the interviewer says the input can contain Unicode, you should immediately think about rune.
Example 1: Reverse a string correctly
This is one of the most common interview questions.
Wrong approach:
package main
func reverseBytes(s string) string {
bytes := []byte(s)
left, right := 0, len(bytes)-1
for left < right {
bytes[left], bytes[right] = bytes[right], bytes[left]
left++
right--
}
return string(bytes)
}
This works for ASCII, but may break for Unicode strings.
Correct approach:
package main
func reverseRunes(s string) string {
runes := []rune(s)
left, right := 0, len(runes)-1
for left < right {
runes[left], runes[right] = runes[right], runes[left]
left++
right--
}
return string(runes)
}
Why this works:
- each element in
runesis one Unicode code point - swapping happens character by character, not byte by byte
Example 2: Palindrome check with Unicode support
package main
func isPalindrome(s string) bool {
runes := []rune(s)
left, right := 0, len(runes)-1
for left < right {
if runes[left] != runes[right] {
return false
}
left++
right--
}
return true
}
This is the preferred pattern when the problem is defined in terms of characters.
Example 3: Character frequency map
If the task is to count characters, use map[rune]int.
package main
import "fmt"
func main() {
s := "a界a界b"
freq := make(map[rune]int)
for _, r := range s {
freq[r]++
}
fmt.Println(freq['a'])
fmt.Println(freq['界'])
}
This is better than map[byte]int when Unicode input is possible.
A subtle but important point
In most interview settings, people casually say “character”.
In real Unicode processing, one visible symbol is not always equal to one rune.
For example, some emoji and accented characters can be formed by multiple code points.
For most Go interview problems, using rune is the correct and expected solution.
But if the problem becomes fully Unicode-display-aware, then even []rune may not be enough.
That is an advanced topic. For standard interviews, remember:
- bytes are for raw UTF-8 data
- runes are for Unicode code points
[]runeis usually the right tool for character-based logic
Common mistakes
Here are the mistakes interviewers often expect you to avoid:
- Using
len(s)as character count - Using
s[i]and thinking it is a full character - Reversing
[]bytefor Unicode strings - Using
map[byte]intfor character frequency when the input may be Unicode - Forgetting that
rangereturns byte index, not rune position
Interview checklist
When you see a string problem in Go, ask yourself:
- Is the input ASCII only, or can it contain Unicode?
- Do I need bytes, or do I need characters?
- Should I iterate with
range? - Do I need to convert to
[]runefor indexing or swapping? - Should my frequency map use
runeas the key?
If the problem is character-based, this pattern is usually safe:
runes := []rune(s)
Then solve the problem on runes.
Summary
To master string interview problems in Go, remember these rules:
- a Go string stores bytes
len(s)gives bytes, not characterss[i]gives a byterunerepresents a Unicode code pointfor rangereads runes from a string[]rune(s)is the correct choice when you need character-based indexing or updates
If you understand these points well, you will avoid many bugs and write interview-ready Go solutions for string problems.
