go教程10

1.     自定义错误

上一教程里,我们学习了 Go 中的错误是如何表示的,并学习了如何处理标准库里的错误。我们还学习了从标准库的错误中提取更多的信息。

在本教程中,我们会学习如何创建我们自己的自定义错误,并在我们创建的函数和包中使用它。我们会使用与标准库中相同的技术,来提供自定义错误的更多细节信息。

使用 New 函数创建自定义错误

创建自定义错误最简单的方法是使用 errors 包中的 New 函数。

在使用 New 函数 创建自定义错误之前,我们先来看看 New 是如何实现的。如下所示,是 errors  中的 New 函数的实现。

// Package errors implements functions to manipulate errors.
package errors
 
// New returns an error that formats as the given text.
 
text 
 
 

    
 
errorString
text

}
 
// errorString is a trivial implementation of error.
 errorString 
 

    s 

}
 
 
e 
errorString
 
 
 

    
 e
s
}

New 函数的实现很简单。errorString 是一个结构体类型,只有一个字符串字段 s。第 14 行使用了 errorString 指针接受者(Pointer Receiver),来实现 error 接口的 Error() string 方法

第 5 行的 New 函数有一个字符串参数,通过这个参数创建了 errorString 类型的变量,并返回了它的地址。于是它就创建并返回了一个新的错误。

现在我们已经知道了 New 函数是如何工作的,我们开始在程序里使用 New 来创建自定义错误吧。

我们将创建一个计算圆半径的简单程序,如果半径为负,它会返回一个错误。

package main
 
 
  
    

    

    

)
 
 
radius 
 
 
 
  
    
 radius 
 
 

        
 
 errors

    

    
 math
Pi 
 radius 
 radius
 

}
 
 
 
  
    radius 
 

    area
 err 
 
radius

    
 err 
 
 

        fmt
err

        

    

    fmt
 area

}

glayground 上运行

在上面的程序中,我们检查半径是否小于零(第 10 行)。如果半径小于零,我们会返回等于 0 的面积,以及相应的错误信息。如果半径大于零,则会计算出面积,并返回值为 nil 的错误(第 13 行)。

在 main 函数里,我们在第 19 行检查错误是否等于 nil。如果不是 nil,我们会打印出错误并返回,否则我们会打印出圆的面积。

在我们的程序中,半径小于零,因此打印出:

Area calculation failed, radius is less than zero

使用 Errorf 给错误添加更多信息

上面的程序效果不错,但是如果我们能够打印出当前圆的半径,那就更好了。这就要用到 fmt 包中的 Errorf 函数了。Errorf 函数会根据格式说明符,规定错误的格式,并返回一个符合该错误的字符串

接下来我们使用 Errorf 函数来改进我们的程序。

package main
 
 
  
    

    

)
 
 
radius 
 
 
 
  
    
 radius 
 
 

        
 
 fmt
 radius

    

    
 math
Pi 
 radius 
 radius
 

}
 
 
 
  
    radius 
 

    area
 err 
 
radius

    
 err 
 
 

        fmt
err

        

    

    fmt
 area

}

playground 上运行

在上面的程序中,我们使用 Errorf(第 10 行)打印了发生错误的半径。程序运行后会输出:

Area calculation failed, radius -20.00 is less than zero

使用结构体类型和字段提供错误的更多信息

错误还可以用实现了 error 接口的结构体来表示。这种方式可以更加灵活地处理错误。在上面例子中,如果我们希望访问引发错误的半径,现在唯一的方法就是解析错误的描述信息 Area calculation failed, radius -20.00 is less than zero。这样做不太好,因为一旦描述信息发生变化,程序就会出错。

我们会使用标准库里采用的方法,在上一教程中“断言底层结构体类型,使用结构体字段获取更多信息”这一节,我们讲解了这一方法,可以使用结构体字段来访问引发错误的半径。我们会创建一个实现 error 接口的结构体类型,并使用它的字段来提供关于错误的更多信息。

第一步就是创建一个表示错误的结构体类型。错误类型的命名约定是名称以 Error 结尾。因此我们不妨把结构体类型命名为 areaError

 areaError 
 
  
    err    

    radius 

}

上面的结构体类型有一个 radius 字段,它存储了与错误有关的半径,而 err 字段存储了实际的错误信息。

下一步是实现 error 接口。

 
e 
areaError
 
 
 
  
    
 fmt
 e
radius
 e
err

}

在上面的代码中,我们使用指针接收者 *areaError,实现了 error 接口的 Error() string 方法。该方法打印出半径和关于错误的描述。

现在我们来编写 main 函数和 circleArea 函数来完成整个程序。

package main
 
 
  
    

    

)
 
 areaError 
 
  
    err    

    radius 

}
 
 
e 
areaError
 
 
 
  
    
 fmt
 e
radius
 e
err

}
 
 
radius 
 
 
 
  
    
 radius 
 
 

        
 
 
areaError
 radius

    

    
 math
Pi 
 radius 
 radius
 

}
 
 
 
  
    radius 
 

    area
 err 
 
radius

    
 err 
 
 

        
 err
 ok 
 err
areaError
 ok 

            fmt
 err
radius

            

        

        fmt
err

        

    

    fmt
 area

}

playground 上运行

在上面的程序中,circleArea(第 17 行)用于计算圆的面积。该函数首先检查半径是否小于零,如果小于零,它会通过错误半径和对应错误信息,创建一个 areaError 类型的值,然后返回 areaError 值的地址,与此同时 area 等于 0(第 19 行)。于是我们提供了更多的错误信息(即导致错误的半径),我们使用了自定义错误的结构体字段来定义它

如果半径是非负数,该函数会在第 21 行计算并返回面积,同时错误值为 nil

在 main 函数的 26 行,我们试图计算半径为 -20 的圆的面积。由于半径小于零,因此会导致一个错误。

我们在第 27 行检查了错误是否为 nil,并在下一行断言了 *areaError 类型。如果错误是 *areaError 类型,我们就可以用 err.radius 来获取错误的半径(第 29 行),打印出自定义错误的消息,最后程序返回退出

如果断言错误,我们就在第 32 行打印该错误,并返回。如果没有发生错误,在第 35 行会打印出面积。

该程序会输出:

Radius -20.00 is less than zero

下面我们来使用上一教程提到的第二种方法,使用自定义错误类型的方法来提供错误的更多信息。

使用结构体类型的方法来提供错误的更多信息

在本节里,我们会编写一个计算矩形面积的程序。如果长或宽小于零,程序就会打印出错误。

第一步就是创建一个表示错误的结构体。

 areaError 
 
  
    err    
 

    length 
 

    width  
 

}

上面的结构体类型除了有一个错误描述字段,还有可能引发错误的宽和高。

现在我们有了错误类型,我们来实现 error 接口,并给该错误类型添加两个方法,使它提供了更多的错误信息。

 
e 
areaError
 
 
 
  
    
 e
err
}
 
 
e 
areaError
 
 
 
  
    
 e
length 
 

}
 
 
e 
areaError
 
 
 
  
    
 e
width 
 

}

在上面的代码片段中,我们从 Error() string 方法中返回了关于错误的描述。当 length 小于零时,lengthNegative() bool 方法返回 true,而当 width 小于零时,widthNegative() bool 方法返回 true这两个方法都提供了关于错误的更多信息,在这里,它提示我们计算面积失败的原因(长度为负数或者宽度为负数)。于是我们就有了两个错误类型结构体的方法,来提供更多的错误信息

下一步就是编写计算面积的函数。

 
length
 width 
 
 
 
  
    err 
 

    
 length 
 
 

        err 
 

    

    
 width 
 
 

        
 err 
 
 

            err 
 

        
 
 

            err 
 

        

    

    
 err 
 
 

        
 
 
areaError
err
 length
 width

    

    
 length 
 width
 

}

上面的 rectArea 函数检查了长或宽是否小于零,如果小于零,rectArea 会返回一个错误信息,否则 rectArea 会返回矩形的面积和一个值为 nil 的错误。

让我们创建 main 函数来完成整个程序。

 
 
  
    length
 width 
 
 

    area
 err 
 
length
 width

    
 err 
 
 

        
 err
 ok 
 err
areaError
 ok 

            
 err
 

                fmt
 err
length

 
            

            
 err
 

                fmt
 err
width

 
            

            

        

        fmt
err

        

    

    fmt
 area

}

在 main 程序中,我们检查了错误是否为 nil(第 4 行)。如果错误值不是 nil,我们会在下一行断言 *areaError 类型。然后,我们使用 lengthNegative() 和 widthNegative() 方法,检查错误的原因是长度小于零还是宽度小于零。这样我们就使用了错误结构体类型的方法,来提供更多的错误信息。

如果没有错误发生,就会打印矩形的面积。

下面是整个程序的代码供你参考。

package main
 
 

 
 areaError 
 
  
    err    
  

    length 
 

    width  
 

}
 
 
e 
areaError
 
 
 
  
    
 e
err
}
 
 
e 
areaError
 
 
 
  
    
 e
length 
 

}
 
 
e 
areaError
 
 
 
  
    
 e
width 
 

}
 
 
length
 width 
 
 
 
  
    err 
 

    
 length 
 
 

        err 
 

    

    
 width 
 
 

        
 err 
 
 

            err 
 

        
 
 

            err 
 

        

    

    
 err 
 
 

        
 
 
areaError
err
 length
 width

    

    
 length 
 width
 

}
 
 
 
  
    length
 width 
 
 

    area
 err 
 
length
 width

    
 err 
 
 

        
 err
 ok 
 err
areaError
 ok 

            
 err
 

                fmt
 err
length

 
            

            
 err
 

                fmt
 err
width

 
            

            

        

        fmt
err

        

    

    fmt
 area

}

playground 上运行

该程序会打印输出:

error: length -5.00 is less than zero  
error: width -9.00 is less than zero

在上一教程错误处理中,我们介绍了三种提供更多错误信息的方法,现在我们已经看了其中两个示例。

第三种方法使用的是直接比较,比较简单。我留给读者作为练习,你们可以试着使用这种方法来给出自定义错误的更多信息。

本教程到此结束。

简单概括一下本教程讨论的内容:

  • 使用 New 函数创建自定义错误
  • 使用 Error 添加更多错误信息
  • 使用结构体类型和字段,提供更多错误信息
  • 使用结构体类型和方法,提供更多错误信息

祝你愉快。

 

posted @   易先讯  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示