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

#### The Problem: Unexpected Behaviour with Leading Zeros

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:

```go
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.

#### Insights into Numeric Literals in Go

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.

#### Avoiding the Trap: Solutions for Consistent Input Interpretation

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:

```go
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
}
```

#### Other Situations to Watch For in Go

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.
    

#### Key Takeaways

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:

1. **Read input as strings** when dealing with user data that could have ambiguous prefixes, and specify the desired base during conversion.
    
2. **Explicitly specify the base** when parsing numeric strings with `strconv` functions to avoid automatic base detection.
    
3. **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.
