关于go的错误处理机制

简介: 关于go的错误处理机制

go的错误处理机制跟php的完全不一样,go讲究的是:

go的错误分为3种:

1:编译时错误,在编译时抛出的错误,例如有变量未出现使用,变量未声明直接使用等,此错误是在运行之前被编译器找出报错的

2:运行时业务自行抛出的错误(Error),此错误可以直接通过函数返回值返回,由调用栈接收处理,如果不处理则不会影响程序运行

3:通过panic 函数抛出的错误,此错误无法被调用栈拦截,但可以在之后由recover接收并忽略,但是无法恢复原来的调用栈

自行抛出的error错误

例如:

package main
import (
   "errors"
   "fmt"
)
func main() {
   var a, b float64
   a = 10
   b = 0
   result, err := division(a, b)
   if err != nil {
      fmt.Printf("出错了:%s", err)
   }
   fmt.Printf("%f 除于 %f 等于 %f", a, b, result)
}
/**
除法
*/
func division(num1, num2 float64) (float64, error) {
   if num2 == 0 {
      return 0, errors.New("0不能作为除数")
   }
   return num1 / num2, nil
}

输出:

出错了:0不能作为除数10.000000 除于 0.000000 等于 0.000000

在示例中,如果函数出现业务异常,只能通过errors.New进行return错误数据,

再由调用函数接收error并做判断处理

也可以声明错误结构体,并声明函数方法实现error接口,使其抛出异常:

package main
import (
   "fmt"
)
type DivideError struct {
   num1 float64
   num2 float64
}
func (receiver DivideError) Error() string  {
   strFormat := `
    Cannot proceed, the divider is zero.
    dividee: %d
    divider: 0
`
   return fmt.Sprintf(strFormat, receiver. num2)
}
func main() {
   var a, b float64
   a = 10
   b = 0
   result,err := division(a, b)
   if err!=nil {
      fmt.Printf("出错了:%s",err)
      return
   }
   fmt.Printf("%f 除于 %f 等于 %f",a,b,result)
}
/**
除法
*/
func division(num1, num2 float64) (float64, error) {
   //if num2 == 0 {
   // return 0, errors.New("0不能作为被除数")
   //}
   fmt.Println(num2)
   if num2 == 0 {
      divisionError := DivideError{num1: num1 ,num2: num2}
      return 0, divisionError
   }
   return num1 / num2,nil
}

输出

GOROOT=/Users/tioncico/sdk/go1.17.6 #gosetup
GOPATH=null #gosetup
/Users/tioncico/sdk/go1.17.6/bin/go build -o /private/var/folders/y7/b5kdfsqx12vchqdhjh4b0mth0000gn/T/\_\_\_go\_build\_LearnGoProject\_ . #gosetup
/private/var/folders/y7/b5kdfsqx12vchqdhjh4b0mth0000gn/T/\_\_\_go\_build\_LearnGoProject\_
0
出错了:
    Cannot proceed, the divider is zero.
    dividee: %!d(float64=0)
    divider: 0

panic函数抛出错误

如果你访问数组时越界,go将自动检查并调用panic抛出错误:

package main
import (
   "fmt"
)
func main() {
   arr := make(\[\]int,3)
   fmt.Println(arr\[4\])
   fmt.Println("结束") //此行不会运行
}

将输出:

GOROOT=/Users/tioncico/sdk/go1.17.6 #gosetup
GOPATH=null #gosetup
/Users/tioncico/sdk/go1.17.6/bin/go build -o /private/var/folders/y7/b5kdfsqx12vchqdhjh4b0mth0000gn/T/\_\_\_go\_build\_main\_go /Users/tioncico/GolandProjects/LearnGoProject/main.go #gosetup
/private/var/folders/y7/b5kdfsqx12vchqdhjh4b0mth0000gn/T/\_\_\_go\_build\_main\_go
panic: runtime error: index out of range \[4\] with length 3
goroutine 1 \[running\]:
main.main()
        /Users/tioncico/GolandProjects/LearnGoProject/main.go:10 +0x1d
Process finished with exit code 2

在panic函数调用后,并不是立即结束进程,而是会调用该协程中的defer函数,例如:

package main
import (
   "fmt"
)
func main() {
   defer func() {
      fmt.Println("defer 1")
   }()
   defer func() {
      fmt.Println("defer 2")
   }()
   defer func() {
      fmt.Println("defer 3")
   }()
   arr := make(\[\]int,3)
   fmt.Println(arr\[4\])
   fmt.Println("结束") //此行不会被运行
}

在结束后,会依次通过栈 先入后出的形式调用defer:

GOROOT=/Users/tioncico/sdk/go1.17.6 #gosetup
GOPATH=null #gosetup
/Users/tioncico/sdk/go1.17.6/bin/go build -o /private/var/folders/y7/b5kdfsqx12vchqdhjh4b0mth0000gn/T/\_\_\_go\_build\_main\_go /Users/tioncico/GolandProjects/LearnGoProject/main.go #gosetup
/private/var/folders/y7/b5kdfsqx12vchqdhjh4b0mth0000gn/T/\_\_\_go\_build\_main\_go
defer 3
defer 2
defer 1
panic: runtime error: index out of range \[4\] with length 3
goroutine 1 \[running\]:
main.main()
        /Users/tioncico/GolandProjects/LearnGoProject/main.go:18 +0x67

可通过 recover接收错误

package main
import (
   "fmt"
)
func main() {
   defer func() {
      err := recover()
      fmt.Println("defer 1")
      fmt.Println("出现了错误:")
      fmt.Println(err)
   }()
   arr := make(\[\]int,3)
   fmt.Println(arr\[4\])
   fmt.Println("结束")
}

输出:

GOROOT=/Users/tioncico/sdk/go1.17.6 #gosetup
GOPATH=null #gosetup
/Users/tioncico/sdk/go1.17.6/bin/go build -o /private/var/folders/y7/b5kdfsqx12vchqdhjh4b0mth0000gn/T/\_\_\_go\_build\_main\_go /Users/tioncico/GolandProjects/LearnGoProject/main.go #gosetup
/private/var/folders/y7/b5kdfsqx12vchqdhjh4b0mth0000gn/T/\_\_\_go\_build\_main\_go
defer 1
出现了错误:
runtime error: index out of range \[4\] with length 3
Process finished with exit code 0

通过recover函数可以获取到错误信息,并且可以通过此信息做一些其他操作(例如记录日志等)

但是可以看出,在recover之后,程序并没有继续运行,("结束"依旧没打印)

如果是在其他调用栈调用的情况:

package main
import (
   "fmt"
)
func main() {
   test()
   fmt.Println("结束")
}
func test()  {
   defer func() {
      err := recover()
      fmt.Println("defer 1")
      fmt.Println("出现了错误:")
      fmt.Println(err)
   }()
   arr := make(\[\]int,3)
   fmt.Println(arr\[4\])
}

将输出:

GOROOT=/Users/tioncico/sdk/go1.17.6 #gosetup
GOPATH=null #gosetup
/Users/tioncico/sdk/go1.17.6/bin/go build -o /private/var/folders/y7/b5kdfsqx12vchqdhjh4b0mth0000gn/T/\_\_\_go\_build\_main\_go /Users/tioncico/GolandProjects/LearnGoProject/main.go #gosetup
/private/var/folders/y7/b5kdfsqx12vchqdhjh4b0mth0000gn/T/\_\_\_go\_build\_main\_go
defer 1
出现了错误:
runtime error: index out of range \[4\] with length 3
结束

可以看到,在其他调用栈调用panic+recover之后,只会影响运行panic的调用栈,而不是影响上层调用

在服务器场景中,可能需要同时处理多个请求,每个请求的操作互不影响,可以通过此操作,使得请求错误之后,不会影响其他请求栈

目录
相关文章
|
C#
使用C#实现随机数生成器
在许多编程任务中,我们经常需要生成随机数。C#编程语言提供了用于生成伪随机数的内置类库。本篇博客将介绍如何使用C#来实现一个简单的随机数生成器。
528 0
|
2月前
|
算法 数据库 C++
软件设计 VS 软件需求:了解成功软件开发外包的关键差异
本文探讨外包软件开发中软件需求与软件设计的关键作用,解析二者定义、区别及在外包项目中的重要性,强调协作沟通与风险管理,助力企业决策者提升项目成功率。
53 0
为什么useState返回的是数组而不是对象?
为什么useState返回的是数组而不是对象?
166 0
|
jenkins Linux 持续交付
WIN版的Jenkins Master加入LINUX的SLAVE节点,并作C++程序的集成交付
这次深撸了一下JENKINS的配置,不敢说完全通了。 但对于整个体系,有了更新认识。 将LINUX作为SLAVE节点加入WIN的JENKINS里,网上有很多教程,依作即可。 在将相关任务分配给这个节点时,需要作相应绑定映射。
1141 0
|
存储 文件存储
通过qt configure -qconfig进一步裁剪
    前一篇讲了可以通过configure脚本来进行配置,但是有许多可以更进一步的配置不能通过configure脚本,或者配置起来非常麻烦,这时就可以借助qconfig工具来进行配置,把不必要的类裁掉,可以看下图qconfig工具截图。
1135 0
|
3天前
|
存储 弹性计算 人工智能
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
2025年9月24日,阿里云弹性计算团队多位产品、技术专家及服务器团队技术专家共同在【2025云栖大会】现场带来了《通用计算产品发布与行业实践》的专场论坛,本论坛聚焦弹性计算多款通用算力产品发布。同时,ECS云服务器安全能力、资源售卖模式、计算AI助手等用户体验关键环节也宣布升级,让用云更简单、更智能。海尔三翼鸟云服务负责人刘建锋先生作为特邀嘉宾,莅临现场分享了关于阿里云ECS g9i推动AIoT平台的场景落地实践。
【2025云栖精华内容】 打造持续领先,全球覆盖的澎湃算力底座——通用计算产品发布与行业实践专场回顾
|
1天前
|
云安全 人工智能 自然语言处理
阿里云x硅基流动:AI安全护栏助力构建可信模型生态
阿里云AI安全护栏:大模型的“智能过滤系统”。
|
2天前
|
人工智能 自然语言处理 自动驾驶
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
关于举办首届全国大学生“启真问智”人工智能模型&智能体大赛决赛的通知
|
5天前
|
存储 机器学习/深度学习 人工智能
大模型微调技术:LoRA原理与实践
本文深入解析大语言模型微调中的关键技术——低秩自适应(LoRA)。通过分析全参数微调的计算瓶颈,详细阐述LoRA的数学原理、实现机制和优势特点。文章包含完整的PyTorch实现代码、性能对比实验以及实际应用场景,为开发者提供高效微调大模型的实践指南。
551 2