使用类型断言在Golang中检测超出范围的值错误。

huangapple go评论83阅读模式
英文:

Detect value out of range errors using type assertion in Golang

问题

给定以下代码:

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

我如何检测函数由于超出int64范围而失败?strconv.ParseInt函数返回一个错误类型,但在这种情况下,它实际上是一个strconv.NumError类型,如%#v所示。Error Handling and Go文章提到可以使用类型断言来检查特定类型的错误,但没有给出任何示例。我应该使用什么表达式来完成这段代码:

if expression {
    uv, err := strconv.ParseUint("18446744073709551448", 10, 64)
}
英文:

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

得分: 11

我们有:

> strconv 包
>
> var ErrRange = errors.New("value out of range")
>
> ErrRange 表示值超出目标类型的范围。
>
> type NumError struct {
> Func string // 失败的函数(ParseBool、ParseInt、ParseUint、ParseFloat)
> Num string // 输入
> Err error // 转换失败的原因(ErrRange、ErrSyntax)
> }
>
> NumError 记录了转换失败的情况。
>
> func (e *NumError) Error() string

例如,

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("检测到", numError.Num, "为", strconv.ErrRange)
				return
			}
		}
		fmt.Println(err)
		return
	}
	fmt.Println(iv)
}

输出:

<pre>
检测到 18446744073709551448 为 value out of range
</pre>

英文:

We have,

> Package strconv
>
> var ErrRange = errors.New(&quot;value out of range&quot;)
>
> 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 (
	&quot;fmt&quot;
	&quot;strconv&quot;
)

func main() {
	iv, err := strconv.ParseInt(&quot;18446744073709551448&quot;, 10, 64)
	if err != nil {
		if numError, ok := err.(*strconv.NumError); ok {
			if numError.Err == strconv.ErrRange {
				fmt.Println(&quot;Detected&quot;, numError.Num, &quot;as a&quot;, strconv.ErrRange)
				return
			}
		}
		fmt.Println(err)
		return
	}
	fmt.Println(iv)
}

Output:

<pre>
Detected 18446744073709551448 as a value out of range
</pre>

答案2

得分: -1

strconv.ParseInt返回的错误在编译时只知道是实现了Error接口的某种类型。类型断言允许您坚持认为它是一个strconv.NumError并直接检查其字段,但如果您发现自己错了,可能会引发运行时恐慌:

if err.(*strconv.NumError).Err.Error() == "value out of range" {
    uv, err := strconv.ParseUint("18446744073709551448", 10, 64)
}

一个更灵活的解决方案(但可能对您的目的来说太宽松)是对err.Error()方法进行子字符串匹配:

if strings.Contains(err.Error(), "value out of range") {
    uv, err := strconv.ParseUint("18446744073709551448", 10, 64)
}
英文:

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() == &quot;value out of range&quot; {
    uv, err := strconv.ParseUint(&quot;18446744073709551448&quot;, 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(), &quot;value out of range&quot;) {
    uv, err := strconv.ParseUint(&quot;18446744073709551448&quot;, 10, 64)
}

huangapple
  • 本文由 发表于 2015年3月11日 10:45:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/28977718.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定