{"record":{"id":"f28a5214000209c9","repo":"unknwon/the-way-to-go_ZH_CN","slug":"d-is-out-of-the-int32-range","errorCode":null,"errorMessage":"%d is out of the int32 range","messagePattern":"(.+?) is out of the int32 range","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"eBook/exercises/chapter_13/panic_defer_convint.go","lineNumber":29,"sourceCode":"\tif i, err := IntFromInt64(l); err != nil {\n\t\tfmt.Printf(\"The conversion of %d to an int32 resulted in an error: %s\", l, err.Error())\n\t} else {\n\t\tfmt.Printf(\"%d converted to an int32 is %d\", l, i)\n\t}\n\tfmt.Println()\n\tl = int64(math.MaxInt32 + 15000)\n\tif i, err := IntFromInt64(l); err != nil {\n\t\tfmt.Printf(\"The conversion of %d to an int32 resulted in an error: %s\", l, err.Error())\n\t} else {\n\t\tfmt.Printf(\"%d converted to an int32 is %d\", l, i)\n\t}\n}\n\nfunc ConvertInt64ToInt(l int64) int {\n\tif math.MinInt32 <= l && l <= math.MaxInt32 {\n\t\treturn int(l)\n\t}\n\tpanic(fmt.Sprintf(\"%d is out of the int32 range\", l))\n}\n\nfunc IntFromInt64(l int64) (i int, err error) {\n\tdefer func() {\n\t\tif e := recover(); e != nil {\n\t\t\terr = fmt.Errorf(\"%v\", e)\n\t\t}\n\t}()\n\ti = ConvertInt64ToInt(l)\n\treturn i, nil\n}\n\n/* Output:\n15000 converted to an int32 is 15000\nThe conversion of 2147498647 to an int32 resulted in an error: 2147498647 is out of the int32 range\n*/\n","sourceCodeStart":11,"sourceCodeEnd":46,"githubUrl":"https://github.com/unknwon/the-way-to-go_ZH_CN/blob/7a54d34d3657084b6a59e5618bd069b912d571aa/eBook/exercises/chapter_13/panic_defer_convint.go#L11-L46","documentation":"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.","triggerScenarios":"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: ...'.","commonSituations":"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.","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"],"exampleFix":"// before\ni := ConvertInt64ToInt(l) // panics on out-of-range; crashes the program\n\n// after\ni, err := IntFromInt64(l)\nif err != nil {\n\tlog.Fatalf(\"conversion failed: %v\", err)\n}","handlingStrategy":"try-catch","validationCode":"if l < math.MinInt32 || l > math.MaxInt32 {\n\treturn 0, fmt.Errorf(\"%d does not fit int32; rejecting before conversion\", l)\n}\nreturn int(l), nil","typeGuard":null,"tryCatchPattern":"i, err := IntFromInt64(l) // recovers the range panic into an error\nif err != nil {\n\treturn fmt.Errorf(\"narrowing %d: %v\", l, err)\n}","preventionTips":["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"],"tags":["go","panic","recover","integer-overflow","conversion"],"backgroundTag":null,"analyzedSha":"7a54d34d3657084b6a59e5618bd069b912d571aa","analyzedAt":"2026-08-15T15:13:06.026Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}