A Guide to Handling Numeric Input in Go: Base Interpretation Mistakes to Avoid

Search for a command to run...

No comments yet. Be the first to comment.
Most people assume the file extension tells the system what type of file it is. It's an intuitive assumption — .png means image, .pdf means document, .exe means executable. At first glance, this seems
Concurrency issues don’t always show up during development—they usually surface when multiple users interact with your system simultaneously. For small-scale applications, this might not even be a concern. But if you’re a developer curious about how ...
Introduction: Campaign management is a critical aspect of any organisation's outreach strategy, and an effective scheduling and execution system can significantly enhance its success. Previously we used to run manual scripts using freshchat apis, whi...

Before we delve into the mechanics of cache invalidation, let's clarify what caching is. A cache, often referred to as a web cache, is a technology designed to store copies of web content, such as web pages, images, and other resources, closer to end...

Recently, while working on a Go program that reverses an integer input, I encountered an unexpected issue: input values with leading zeros produced incorrect results. For example, entering 0123 returned 83 instead of 321. After some debugging, I realised the cause was rooted in Go's interpretation of numeric literals.
Here’s a simplified version of the code:
package main
import "fmt"
func main() {
var inp int
fmt.Scan(&inp)
fmt.Println(inp) // Outputs unexpected values for leading-zero inputs
}
Entering 0123 resulted in 83, a behaviour that puzzled me at first. Why would Go interpret 0123 as 83? Let’s dive into the mechanics behind Go’s input handling to understand this better.
In Go, numeric literals are interpreted based on their prefixes:
Decimal: Numbers without any prefix (e.g., 123) are treated as decimal.
Octal: Numbers starting with 0 (like 0123) are interpreted as octal (base 8).
Hexadecimal: Numbers prefixed with 0x or 0X (like 0x1F) are hexadecimal (base 16).
Binary: Numbers prefixed with 0b or 0B (like 0b1010) are binary (base 2). This was introduced in Go 1.13.
Because 0123 has a 0 prefix, Go treats it as an octal number, converting it to 83 in decimal, which explains the unexpected output.
If you’re dealing with user input that might include leading zeros and you want decimal interpretation, consider reading the input as a string and then converting it explicitly to an integer. Here’s an improved version of the original code:
package main
import (
"fmt"
"strconv"
)
func main() {
var inp string
fmt.Scan(&inp)
num, err := strconv.Atoi(inp)
if err != nil {
fmt.Println("Invalid input")
return
}
fmt.Println(num) // Now it will interpret as decimal regardless of leading zeros
}
This behaviour isn't limited to fmt.Scan:
String parsing with strconv.ParseInt: Setting the base to 0 in functions like strconv.ParseInt("0123", 0, 64) will detect the base from prefixes. If consistent decimal interpretation is needed, specify 10 as the base instead.
Hexadecimal and binary literals in code: These are helpful, but make sure they’re not used inadvertently, as 0x and 0b prefixes will trigger hexadecimal and binary parsing.
This experience taught me the importance of understanding how Go interprets numeric literals. Here’s a summary of best practices when handling numeric input in Go:
Read input as strings when dealing with user data that could have ambiguous prefixes, and specify the desired base during conversion.
Explicitly specify the base when parsing numeric strings with strconv functions to avoid automatic base detection.
Watch out for leading zeros in integer input, especially in cases where the base might unintentionally switch to octal.
Understanding these nuances can prevent bugs and ensure that your Go programs handle numeric inputs predictably.