Определите значение вне диапазона ошибок, используя утверждение типа в 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
, В статье Обработка ошибок и Go упоминается, что вы можете использовать утверждение типа для проверки ошибок определенного типа, но в ней нет примеров. Какое выражение я должен использовать для завершения этого кода:
if expression {
uv, err := strconv.ParseUint("18446744073709551448", 10, 64)
}
2 ответа
У нас есть,
var ErrRange = errors.New("value out of range")
ErrRange указывает, что значение выходит за пределы диапазона для целевого типа.
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) }
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("Detected", numError.Num, "as a", strconv.ErrRange)
return
}
}
fmt.Println(err)
return
}
fmt.Println(iv)
}
Выход:
Обнаружено 18446744073709551448 как значение вне диапазона
Ошибка, которая возвращается из 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)
}