问题
Given the following code:
iv, err := strconv.ParseInt("18446744073709551448", 10, 64)
fmt.Println(iv)
fmt.Printf("%#v\n", err)
fmt.Printf("%v\n", err)
//Output:
9223372036854775807
&strconv.NumError{Func:"ParseInt", Num:"18446744073709551448", Err:(*errors.errorString)(0x1040a040)}
strconv.ParseInt: parsing "18446744073709551448": value out of range
How can I detect that the function failed due to being out of range of an int64? The strconv.ParseInt function returns an error type, but in this case it is actually a strconv.NumError type as indicated by %#v
. The Error Handling and Go article mentions you can use type assertion to check for specific types of errors, but it doesn't give any examples. What expression should I use to complete this code:
if expression {
uv, err := strconv.ParseUint("18446744073709551448", 10, 64)
}
回答1:
We have,
Package strconv
var ErrRange = errors.New("value out of range")
ErrRange indicates that a value is out of range for the target type.
type NumError struct { Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat) Num string // the input Err error // the reason the conversion failed (ErrRange, ErrSyntax) }
A NumError records a failed conversion.
func (e *NumError) Error() string
For example,
package main
import (
"fmt"
"strconv"
)
func main() {
iv, err := strconv.ParseInt("18446744073709551448", 10, 64)
if err != nil {
if numError, ok := err.(*strconv.NumError); ok {
if numError.Err == strconv.ErrRange {
fmt.Println("Detected", numError.Num, "as a", strconv.ErrRange)
return
}
}
fmt.Println(err)
return
}
fmt.Println(iv)
}
Output:
Detected 18446744073709551448 as a value out of range
回答2:
The error that's returned from strconv.ParseInt
is only known at compile time to be some type that implements the Error interface. Type assertion allows you to insist that it's a strconv.NumError
and inspect its fields directly, but at the risk of throwing a runtime panic if you turn out to be wrong:
if err.(*strconv.NumError).Err.Error() == "value out of range" {
uv, err := strconv.ParseUint("18446744073709551448", 10, 64)
}
A more flexible solution (but maybe too loosey-goosey for your purposes) would be to perform a substring match on the err.Error()
method:
if strings.Contains(err.Error(), "value out of range") {
uv, err := strconv.ParseUint("18446744073709551448", 10, 64)
}
来源:https://stackoverflow.com/questions/28977718/detect-value-out-of-range-errors-using-type-assertion-in-golang