unknwon/the-way-to-go_ZH_CN · error
%d is out of the int32 range
Error message
%d is out of the int32 range
What it means
Chapter 13 exercise (panic_defer_convint.go): ConvertInt64ToInt panics with fmt.Sprintf("%d is out of the int32 range", l) when the int64 argument falls outside [math.MinInt32, math.MaxInt32]. Its wrapper IntFromInt64 demonstrates converting a panic into an error: a deferred recover catches the panic and builds err via fmt.Errorf("%v", e), so callers get a formatted range error instead of a crash — which is exactly what main tests with math.MaxInt32 + 15000.
Source
Thrown at eBook/exercises/chapter_13/panic_defer_convint.go:29
if i, err := IntFromInt64(l); err != nil {
fmt.Printf("The conversion of %d to an int32 resulted in an error: %s", l, err.Error())
} else {
fmt.Printf("%d converted to an int32 is %d", l, i)
}
fmt.Println()
l = int64(math.MaxInt32 + 15000)
if i, err := IntFromInt64(l); err != nil {
fmt.Printf("The conversion of %d to an int32 resulted in an error: %s", l, err.Error())
} else {
fmt.Printf("%d converted to an int32 is %d", l, i)
}
}
func ConvertInt64ToInt(l int64) int {
if math.MinInt32 <= l && l <= math.MaxInt32 {
return int(l)
}
panic(fmt.Sprintf("%d is out of the int32 range", l))
}
func IntFromInt64(l int64) (i int, err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("%v", e)
}
}()
i = ConvertInt64ToInt(l)
return i, nil
}
/* Output:
15000 converted to an int32 is 15000
The conversion of 2147498647 to an int32 resulted in an error: 2147498647 is out of the int32 range
*/
View on GitHub (pinned to 7a54d34d36)
Solutions
- Call IntFromInt64 (the recover wrapper) instead of ConvertInt64ToInt when the value is untrusted — it returns the error instead of crashing the process
- Pre-check the range: if l < math.MinInt32 || l > math.MaxInt32 { handle } before any conversion
- Redesign the API to return an error natively (range check + return 0, err) and reserve panic for programmer errors — the generalization of this exercise
- Where possible keep values int64 end-to-end so no narrowing conversion exists
Example fix
// before
i := ConvertInt64ToInt(l) // panics on out-of-range; crashes the program
// after
i, err := IntFromInt64(l)
if err != nil {
log.Fatalf("conversion failed: %v", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if l < math.MinInt32 || l > math.MaxInt32 {
return 0, fmt.Errorf("%d does not fit int32; rejecting before conversion", l)
}
return int(l), nil Try / catch
i, err := IntFromInt64(l) // recovers the range panic into an error
if err != nil {
return fmt.Errorf("narrowing %d: %v", l, err)
} Prevention
- Range-check before every int64→int32/int conversion; silent truncation wraps and flips signs
- Keep 64-bit values int64 end-to-end; narrow only at the final boundary that truly requires 32 bits
- Treat nanosecond timestamps, hashes, and DB IDs as routine int32-overflow sources
- If a panicking helper must stay, always call it through the recover-wrapping variant at package boundaries
When it happens
Trigger: ConvertInt64ToInt(l) with any l beyond ±(2^31-1): the range check math.MinInt32 <= l && l <= math.MaxInt32 fails and the panic fires. Calling IntFromInt64(l) instead turns it into the returned error, printing 'The conversion of 2148979647 to an int32 resulted in an error: ...'.
Common situations: Nanosecond timestamps, hashes, database IDs, and file sizes exceeding 2^31; migrating code between 32/64-bit platforms where int/int64 widths differ; the exercise's own lesson — converting panicking library calls into error returns at a package boundary.
Related errors
AI-assisted analysis of unknwon/the-way-to-go_ZH_CN@7a54d34d36 (2026-08-15).
Data as JSON: /api/errors/f28a5214000209c9.
Report an issue: GitHub.