代码之家  ›  专栏  ›  技术社区  ›  sofs1 Romain Manni-Bucau

为什么Golang接受一个自定义结构来代替错误类型?

  •  0
  • sofs1 Romain Manni-Bucau  · 技术社区  · 5 年前

    https://tour.golang.org/methods/20

    package main
    
    import (
        "fmt"
        "math"
    )
    
    type ErrNegativeSqrt float64 //This is the custom Struct
    
    func (e ErrNegativeSqrt) Error() string { 
        return fmt.Sprintf("cannot Sqrt negative number: %g", float64(e))
    }
    
    func Sqrt(x float64) (float64, error) {  // Is error a type ?
        if(x < 0){
            return x, ErrNegativeSqrt(x) //Q1) If error is a type, How come  ErrNegativeSqrt(x) is of type error?
        }       
        z := float64(1.5)
        val := float64(0)
        for {
            z = z - (z*z-x)/(2*z)
            if math.Abs(val-z) < 1e-10 {
                break
            }
            val = z
        }
        return val, nil
    }
    
    func main() {
        fmt.Println(Sqrt(2))
        fmt.Println(Sqrt(-2))
    }
    

    问题2)为什么打电话给快速冲刺(e) 内部的错误方法会将程序发送到一个无限循环中吗?

    1 回复  |  直到 5 年前
        1
  •  3
  •   torek    5 年前

    加油 interface

    不过,值得纠正的是:

    type ErrNegativeSqrt float64 //This is the custom Struct
    

    这不是一个 struct 类型。 float64 它本身就是一个预先声明的 数字类型 , as defined here in the Go reference :

    数字类型 表示整数值或浮点值集。预先声明的与体系结构无关的数字类型是:[此处截取了各种条目]

    float64     the set of all IEEE-754 64-bit floating-point numbers
    

    你的 type 这里的声明创建了一个名为 ErrNegativeSqrt 那已经 作为它的 基础类型 ;参见 the Types section .

    类型任何类型,无论 或其他 工具 the Interface types section 全貌。加油 error the Errors section :

    错误 定义为

    type error interface {
        Error() string
    }
    

    这意味着无论何时定义自己的类型 用户 ,如果添加这样的行:

    func (varname UserT) Error() string {
        // return some string here
    }
    

    您定义的类型 用户 实现错误接口 . 因此,你可以 转换 任何类型的值 用户 通过简单的分配。看到了吗 the Assignability section ,包括:

    价值观 x 可转让的 类型的变量 T ... 如果下列条件之一适用:[某些项目符号被剪断]

    • T型 是接口类型和

    我们刚刚看到了 错误 错误 ,并且你有一些现有的价值 类型 UserT 用户 Error() string 错误 . 也就是说 ErrNegativeSqrt公司 像你那样设置,并且:

    var x ErrNegativeSqrt
    // set `x` to some valid value
    
    // and:
    var e error
    

    然后:

    e = x
    

    进入之内 e ,尽管 类型 电子 是接口类型,而不是 .

    进入之内 就像这样,编译器实际上设置 里面的东西 电子 . 换句话说, 就像两元素数组,或者 两个字段,但不能使用下标或 .field 键入拼写。

    电子 的价值是 . 这两个值中的另一个是 的实际值,复制到 电子 .

    换句话说,编译器将:

    e=x
    

    e.value = x
    e.type = ErrNegativeSqrt
    

    不过,再说一次,你不能 e.type e.value . 编译器执行两个部分

    You should have already seen how you can pick apart the two parts of things stored into e if necessary. 经常是这样 必要的,特别是如果接口设计良好的话。但是,在对中的错误返回进行了实验之后,值得回溯到本教程的这些早期部分 #20 .

        2
  •  1
  •   Eldar    5 年前

    Error是定义 Error() string

    func (e ErrNegativeSqrt) Error() string { 
        return fmt.Sprintf("cannot Sqrt negative number: %g", float64(e))
    }
    

    而这个代码正是这么做的。现在你的 ErrNegativeSqrt

    if(x < 0){
            return x, ErrNegativeSqrt(x) // totally fine.
        }
    

    文件 error