深入探究Go语言的错误策略与异常机制

2024-03-01 0 385
目录
  • 前言
  • Go错误处理策略
    • 创建error的几种方式
      • errors包
      • fmt包
      • 自定义错误类型
    • 如何处理错误
      • 直接返回错误
      • 记录日志并继续运行
      • 记录日志并结束运行
  • Go异常处理机制
    • panic函数
      • recover函数
      • 总结

        前言

        作为开发者来说,我们没办法保证程序在运行过程中永远不会出现异常,对于异常,在很多编程语言中,可以用 try-catch语句来捕获,而Go语言的开发者显然觉得 try-catch被滥用了,因此 Go不支持使用 try-catch语句捕获异常处理。

        那么,Go语言是如何定义和处理程序的异常呢?

        Go语言的将程序运行出现的问题分为两种:错误(error)和异常(exception),错误是程序(比如一个函数)运行的预期结果之一,当你调用一个函数时,就应该处理出现错误的情况,而异常是不可预期的(当然也可以手动触发)且会导致程序中断运行的严重错误。

        Go错误处理策略

        编写Go语言程序,一般推荐通过函数的最后一个返回值告诉调用者函数是否执行成功,可以分两种情况来讨论:

        第一种情况,如果函数的执行结果只有正确与失败,那么返回值可以是boolean类型:

        func exists(key string) bool {
        //to check if the key is exists
        return true
        }

        if ok := exists(\”test\”); ok {
        // do something
        }

        第二种情况,如果要让调用者得到更详细的错误信息,显然只返回一个布尔值是不够的,这时候可以返回一个error类型,error类型是一个接口,只有一个Error方法的接口:

        type error interface {
        Error() string
        }

        通过error类型的Error方法,可以获得更详细的错误信息,方便调用者做进一步的处理,因此在Go标准库的方法和函数中,一般都会将error类型作为最后一个返回值,比如我们以前文章中讲到的os包下的Open和Create函数:

        package os

        func Open(name string) (*File, error) {
        return OpenFile(name, O_RDONLY, 0)
        }

        func Create(name string) (*File, error) {
        return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
        }

        当函数最后一个返回值error不为nil时,表示执行不成功,此时其他的返回值就应该忽略:

        file,err := os.Open(\”./my.dat\”)

        if err != nil{
        return err
        }

        defer file.Close()

        上面代码中,如果 error不为 nil,那么变量 file则为 nil,表示无法获得一个文件句柄,这时候直接返回错误,因为如果再继续往下执行,可能会引发程序崩溃。

        当然并不是所有情况下一遇到返回的 error不为 nil,就要抛弃其他返回值,比如使用 Read()方法读取文件时:

        Read(p []byte) (n int, err error)

        在读取文件到结尾时Read方法会返回一个io.EOF的错误:

        var EOF = errors.New(\”EOF\”)

        此时虽然error不为nil,但仍然应该把读取到的字节数组保存,而不是抛弃掉。

        创建error的几种方式

        当我们开发自己的函数时,也可以创建自己的错误类型,有以下几种方式:

        errors包

        errors包下的New()函数可以创建一个只有文本信息的error类型:

        package main

        func main() {
        var s = []int{1, 2, 3}
        s[3] = 10
        }

        fmt包

        fmt包下的Errorf函数可以将文本格式后作为error类型的错误信息,并返回一个error类型,因此其作用与errors.New函数类似

        func getFile(name string)(*os.file,error){
        if name == \”\”{
        return nil,fmt.Errorf(\”file name could not be empty\”)
        }
        }

        fmt.Errorf函数还能封装其他error类型,再返回一个新的error类型,以此形成一条完整的错误链条:

        doc, err := html.Parse(resp.Body)
        resp.Body.Close()
        if err != nil {
        return nil, fmt.Errorf(\”parsing %s as HTML: %v\”, url,err)
        }

        自定义错误类型

        其实,上面两种创建错误类型的方式,本质上都是实现error接口,我们也可以创建一个拥有Error方法的类型来实现error接口:

        type Result struct {
        Code int
        Message string
        Data interface{}
        }

        func (r Result) Error() string {
        return r.Message
        }

        如何处理错误

        当调用的函数或方法的返回值有error类型时,最简单的当然可以选择直接忽略错误,不过更恰当的方式是处理对应的错误,有以下几种处理策略:

        直接返回错误

        对于函数来说,如果在执行时遇到错误,可以直接返回给上层调用者:

        func SendMessage(url string) error {
        if url == \”\”{
        return errors.New(\”url can\’t not be empty\”)
        }
        _, err := http.Get(url)
        if err != nil {
        return err
        }
        return nil
        }

        记录日志并继续运行

        当调用函数时遇到返回的错误,如果不影响程序运行,也可以选择记录错误日志并往下执行:

        if err := SendMessage(\”https://xxx/sendMessage\”);err != nil{
        log.Printf(\”the message sending been broken by : %v\\n\”, err)
        }

        记录日志并结束运行

        如果错误影响程序的执行,也可以记录日志后,退出程序执行:

        if err := SendMessage(\”https://xxx/sendMessage\”);err != nil{
        log.Printf(\”the message sending been broken by : %v\\n\”, err)
        os.Exit(1)
        }

        记录日志并退出执行,直接用log包的Fatalf函数就可以做到,因此上面代码的更简洁做法是:

        if err := SendMessage(\”https://xxx/sendMessage\”);err != nil{
        log.Fatalf(\”the message sending been broken by : %v\\n\”, err)
        }

        Go异常处理机制

        在Go语言中,异常是指会引发程序崩溃无法继续运行的错误,比如数组越界或者空指针引用等情况,这时候会触发panic异常:

        package main

        func main() {
        var s = []int{1, 2, 3}
        s[3] = 10
        }

        上面程序运行结果如下,可以看出触发了数组越界的异常:

        panic: runtime error: index out of range [3] with length 3

        无论是在主协程还是子协程中,一旦触发panic异常,整个程序都会终止运行。

        panic函数

        除了数组越界等不可预测的异常会自动触发panic,也可以手动调用panic函数触发异常来终止程序的运行:

        func loadConfig(path string){
        panic(\”can\’t load the config file on path \” + path)
        }

        一个良好的程序最好不要主动调用panic函数,尤其是开发类库的时候,最好通过返回error类型来告诉调用者发生了什么错误,而不是触发panic导致程序终止运行。

        recover函数

        当发生panic异常时,如果不捕获得异常,那么程序就是终止运行,在Go语言中,可以用defer语句和recover函数的模式来捕获panic异常:

        package main

        import (
        \”fmt\”
        \”log\”
        )

        func main() {

        n1 := FindElementByIndex(1)
        fmt.Println(n1)

        n2 := FindElementByIndex(4)
        fmt.Println(n2)
        }

        func FindElementByIndex(index int) int {
        defer func() {
        if e := recover(); e != nil {
        log.Fatal(e)
        }
        }()
        s := []int{1, 2, 3, 4}
        return s[index]
        }

        总结

        本文深入探讨了Go语言的错误策略与异常机制。主要介绍了错误处理的重要性,以及Go语言中的错误类型和处理函数。此外还讨论了Go语言的异常机制,包括panic和recover函数的使用。通过合理的错误处理和异常处理,我们可以提高代码的可维护性和可靠性,减少潜在的bug和故障。希望本文对您有帮助,感谢阅读~

        以上就是深入探究Go语言的错误策略与异常机制的详细内容,更多关于Go错误策略与异常机制的资料请关注悠久资源网其它相关文章!

        您可能感兴趣的文章:

        • Golang异常控制处理程序错误流程
        • Go错误处理之panic函数和recover函数使用及捕获异常方法
        • Golang错误处理方式异常与error
        • Go中的错误和异常处理最佳实践方法
        • Go语言学习笔记之错误和异常详解

        收藏 (0) 打赏

        感谢您的支持,我会继续努力的!

        打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
        点赞 (0)

        悠久资源 Golang 深入探究Go语言的错误策略与异常机制 https://www.u-9.cn/jiaoben/golang/179410.html

        常见问题

        相关文章

        发表评论
        暂无评论
        官方客服团队

        为您解决烦忧 - 24小时在线 专业服务