The Problem: Converting Rune to Int in Go
When working with strings and characters in Go, you'll often need to convert a rune (Go's representation of a Unicode code point) to its integer value. This is a common task when parsing numeric strings character by character.
If you try the obvious approach of using int(rune), you won't get the expected result. Instead of getting the numeric value of the digit, you'll get its ASCII/Unicode code point.
Why Does int(rune) Return the Wrong Value?
Let's understand why simply casting a rune to int doesn't work as expected:
package main
import "fmt"
func main() {
r := '8'
result := int(r)
fmt.Println(result) // Output: 56, not 8!
}
The output is 56, not 8. This happens because int(rune) returns the Unicode code point of the character, not the numeric value it represents.
Understanding ASCII Codes for Digits
The ASCII codes for digits 0-9 are sequential, ranging from 48 to 57:
| Character | ASCII Code |
|---|---|
| '0' | 48 |
| '1' | 49 |
| '2' | 50 |
| '3' | 51 |
| '4' | 52 |
| '5' | 53 |
| '6' | 54 |
| '7' | 55 |
| '8' | 56 |
| '9' | 57 |
When you convert rune '8' to int, you get 56 because that's the ASCII code for the character '8'.
The Solution: Subtract '0' from the Rune
To convert a rune to its actual integer value, subtract the rune '0' (which has ASCII value 48):
int(r - '0')
This works because all digit characters are sequential in ASCII. By subtracting '0' (48), you get the offset from 0, which is the actual numeric value.
Complete Working Example
package main
import "fmt"
func main() {
// Single rune conversion
r := '8'
value := int(r - '0')
fmt.Printf("Rune '%c' converted to int: %d\n", r, value)
// Output: Rune '8' converted to int: 8
// Converting a string of digits
str := "12345"
fmt.Print("Converting string '12345': ")
for _, char := range str {
num := int(char - '0')
fmt.Printf("%d ", num)
}
fmt.Println()
// Output: Converting string '12345': 1 2 3 4 5
}
Converting String to Integer (Digit by Digit)
Here's a practical example of parsing an integer from a string manually:
package main
import "fmt"
func stringToInt(s string) int {
result := 0
for _, r := range s {
result = result*10 + int(r-'0')
}
return result
}
func main() {
num := stringToInt("42")
fmt.Println(num) // Output: 42
num2 := stringToInt("9876")
fmt.Println(num2) // Output: 9876
}
Handling Non-Digit Characters
When working with user input, always validate that the rune is actually a digit:
package main
import (
"fmt"
"unicode"
)
func runeToInt(r rune) (int, bool) {
if unicode.IsDigit(r) {
return int(r - '0'), true
}
return 0, false
}
func main() {
// Valid digit
if val, ok := runeToInt('7'); ok {
fmt.Printf("Converted: %d\n", val)
}
// Invalid character
if _, ok := runeToInt('x'); !ok {
fmt.Println("Not a valid digit")
}
}
Alternative: Using strconv Package
For more complex conversions, Go's strconv package provides robust functions:
package main
import (
"fmt"
"strconv"
)
func main() {
// Convert string to int
num, err := strconv.Atoi("42")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(num) // Output: 42
// Convert single character string
digit, _ := strconv.Atoi(string('8'))
fmt.Println(digit) // Output: 8
}
Summary
To convert a rune to an int in Go:
- Don't use
int(rune)directly — it returns the ASCII/Unicode code point - Use
int(rune - '0')to get the actual numeric value - Validate input with
unicode.IsDigit()for safety - Consider
strconv.Atoi()for string-to-integer conversions
This technique works because digit characters are sequential in ASCII, so subtracting '0' gives you the offset (the actual digit value).