Detect value out of range errors using type assertion in Golang

核能气质少年 提交于 2019-12-08 07:16:21

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!