为了账号安全,请及时绑定邮箱和手机立即绑定

我想了解为什么要创建一种类型来处理 Go 中的错误,以及您如何决定它应该具有什么基础类型

我想了解为什么要创建一种类型来处理 Go 中的错误,以及您如何决定它应该具有什么基础类型

Go
繁星coding 2021-12-20 19:13:21
我正在完成A Tour of Go - 练习:错误。当我向平方根函数添加错误处理时,它握住了我的手。这是我的解决方案:package mainimport (    "fmt"    "math")type ErrNegativeSqrt float64func (e ErrNegativeSqrt) Error() string {    fmt.Sprint(float64(e))    return fmt.Sprintf("cannot Sqrt negative number: %g", float64(e))}func Sqrt(x float64) (float64, error) {    z := 1.0    margin := 0.00000000000001    for {        if x < 0 {            return 0, ErrNegativeSqrt(x)        }        previousZ := z        z = z - (z*z-x)/(2*z)        if math.Abs(previousZ-z) < margin {            fmt.Println(previousZ, "-", z, "=", previousZ-z)            break        }    }    fmt.Println("math.Sqrt:", math.Sqrt(x))    return z, nil}func main() {    fmt.Println(Sqrt(2))    fmt.Println(Sqrt(-2))}我无法理解这条线:type ErrNegativeSqrt float64我有两个问题:为什么 ErrNegativeSqrt 的底层类型是“float64”而不是“error”?和为什么首先要创建一个类型?为什么我们要创建一个错误类型并向其添加一个方法,而不是仅仅拥有一个独立的函数?我是 Go 的初学者,我想了解一下。太感谢了。
查看完整描述

3 回答

?
慕的地8271018

TA贡献1796条经验 获得超4个赞

我将首先回答您的第二个问题:您向类型添加一个方法,以便 ErrNegativeSqrt 实现错误接口,这意味着不了解 ErrNegativeSqrt 细节的其他代码可以将其用作任何其他错误。


由于错误接口只需要一个返回类型为字符串的方法 Error(),所以常用的类型只是一个字符串,错误方法返回该字符串(在包“errors”中定义)。


我不知道为什么在这种情况下决定使用 float64 作为错误类型,但我看到的主要优点是,如果您有多个可能返回类似错误的函数,则必须执行以下操作:


func Method1() error{

  ...

  return errors.New(fmt.Sprintf("cannot Sqrt negative number: %g", number)

}


func Method2() error{

  ...

  return errors.New(fmt.Sprintf("cannot Sqrt negative number: %g", number2)

}

并重复任何需要返回类似内容的函数。使用您发布的代码,您只需在创建错误时声明造成错误的数字,并且方法“Error()”返回所有格式化的字符串。


func Method1() error{

  ...

  ErrNegativeSqrt(number)

}


func Method2() error{

  ...

  ErrNegativeSqrt(number)

}


查看完整回答
反对 回复 2021-12-20
?
繁星淼淼

TA贡献1775条经验 获得超11个赞

通常不会创建自定义错误类型,但这是对错误如何工作以及其他一些 Go 概念的演示。

为什么 ErrNegativeSqrt 的底层类型是“float64”而不是“error”?

这允许将float64值 inSqrt直接转换为错误。它还演示了新类型如何可以具有各种基础类型,并且方法可以附加到结构以外的类型。如果您需要创建自己的错误类型,请使用最适合您的用例的基础类型。

为什么首先要创建一个类型?为什么我们要创建一个错误类型并向其添加一个方法,而不是仅仅拥有一个独立的函数?

有时,错误需要比从errors.New, 或返回的单个字符串中包含的信息或上下文更多fmt.Errorf。例如,net包使用a net.OpError(符合net.Error接口)来打包地址信息,无论是临时错误,还是超时引起的。

在大多数情况下,一个简单的基于字符串的错误就足够了。


查看完整回答
反对 回复 2021-12-20
?
九州编程

TA贡献1785条经验 获得超4个赞

像任何其他语言一样,我们创建一个类型或对象来为我们自己的利益和功能分组(计算机不关心)。在 Go 中,创建自定义类型或结构类型来扩展对象的功能是很常见的。


在这种情况下,创建类型ErrNegativeSqrt实际上可以float64通过添加方法来扩展功能。例如,比较这两种方法:


func TimesTwo(val int) int {

        return val * 2

}


type SuperChargedInt int


func (sc SuperChargedInt) TimesTwo() int {

        return int(sc) * 2

}

a 不是将 an 传递int给函数,而是SuperChargedInt具有作用于自身的能力。当您进入界面时,这变得非常方便。


type MyInt interface {

        TimesTwo() int

}


type IntA int

type IntB int


func (a IntA) TimesTwo() int {

        return int(a) * 2

}


func (b IntB) TimesTwo() int {

        return int(b) * (1 + 1)

}


func PrintMyInt(c MyInt) {

        fmt.Println(c)

}

类型IntA和IntB满足接口,MyInt因为它们都实现了所需的方法,可以在需要 的代码中的任何地方使用MyInt。


var a IntA = 34

var b IntB = 32

PrintMyInt(a)

PrintMyInt(b)


type SomeNum struct {

        A MyInt

}


num := SomeNum{ A: a }

理解了接口,现在回到ErrNegativeSqrt类型,Error()给它添加方法,让类型实现error接口(只有一个方法Error()要实现)。现在你可以在任何地方像错误一样使用类型。


这是 Golang 中的鸭子类型。


查看完整回答
反对 回复 2021-12-20
  • 3 回答
  • 0 关注
  • 172 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信