Go-异常处理(defer recover panic)

简介: Go-异常处理(defer recover panic)

前言


提示:这里可以添加本文要记录的大概内容:

Go 语言在运行当中会出现panic ,为了解决和避免该问题学习defer,panic, recover 关键字


一、关键字含义


defer /recover 实现异常捕获和处理

defer 主要是指定一个延迟调用函数;

recover 发生异常的时候,可以去恢复我们的一个协程,并且拿到一个导致协程中断的消息。


应用场景

  1. 资源释放: 文件操作,打开文件,判断没有错误的情况下,立马去声明一个defer 调用(file close)关闭; 网络连接,tcp 连接建立连接成功之后,就可以调用defer 去关闭;
  2. 异常捕获和处理: 方法bi’r结束(异常结束和正常结束),都会触发defer 调用 ;


defer

  1. defer 关键字用来声明一个延迟调用函数,该函数可以是匿名函数也可以是具名函数
  2. defer 延迟函数执行时间(位置),方法return 之后,返回参数到调用方法之前; A调用B, defer 在B方法return 之后,但是在B方法值返回之前
  3. defer 延迟函数可以在方法返回之后改变改变函数的返回值;不是任何值都可改变,若依值类型返回不会受影响。依指针全局变量可以改变;
  4. 在方法结束(正常退出,异常结束)都会去调用defer声明的延迟函数,可以有效避免因异常导致的资源无法释放的问题;
  5. 可以指定多个defer延迟函数,多个延迟函数执行顺序为后进先出;
  6. defer 通常用于资源释放,异常捕获等场景。例如: 关闭连接,关闭文件等;
  7. defer与recover 配合可以实现异常捕获与处理逻辑;
  8. 不建议在for 循环中使用defer;


recover

  1. Go 语言内置函数,可以让进入宕机流程中的goroutine 恢复过来;比如A方法中五个步骤,在第三个触发了异常触发了defer 函数,那么recover 恢复后第三个步骤之后的步骤是不会执行。恢复协程使应用比较稳定,并不意味之按照之前的流程走。
  2. recover 仅在延迟函数,defer 中有效, 在正常的执行过程中,调用recover 会返回nil并且没有其他任何效果;
  3. 如果当前的goroutine 出现panic(其它语言说的异常),调用recover可以捕获到panic的输入值,并且恢复正常执行;


panic

  1. Go 语言的一种异常机制;
  2. 可以通过panic 函数主动抛出异常


二、实例


实例讲解上述几种情况

代码如下(示例):创建dir; main.go case/defer.go

// case/defer.go
package _case
import (
  "fmt"
  "io"
  "log"
  "os"
)
// defer 关键字用来声明一个延迟调用函数
// 该函数可以是匿名函数也可以是具名函数
// defer 延迟函数的执行顺序为后进先出
func DeferCase1() {
  fmt.Println("开始执行DeferCase1")
  defer func() {
    fmt.Println("调用了匿名函数1")
  }()
  defer f1()
  defer func() {
    fmt.Println("调用了匿名函数2")
  }()
  fmt.Println("DeferCase1执行结束")
}
// 参数预计算
func DeferCase2() {
  i := 1
  defer func(j int) {
    fmt.Println("defer J:", j)
  }(i + 1)
  // 闭包
  defer func() {
    fmt.Println("defer j:", i)
  }()
  i = 99
  fmt.Println("i:", i)
}
// 返回值
// defer 函数执行在return 之后
func DeferCase3() {
  i, j := f2()
  fmt.Printf("j:%d,j:%d,g:%d", i, *j, g)
}
func f1() {
  fmt.Println("调用了具名函数1")
}
var g = 100
func f2() (int, *int) {
  defer func() {
    g = 200
  }()
  fmt.Println("f2 g:", g)
  return g, &g
}
func FileReadCase() {
  file, err := os.Open("README.md")
  if err != nil {
    log.Fatal(err)
  }
  //通过defer 调用资源释放方法
  defer func() {
    file.Close()
    fmt.Println("释放文件资源")
  }()
  buf := make([]byte, 1024)
  for {
    n, err := file.Read(buf)
    if err != nil && err != io.EOF {
      log.Fatal(err)
    }
    if n == 0 {
      break
    }
    fmt.Println(buf[:n])
  }
}
func ExceptionCase() {
  defer func() {
    // 捕获异常, 恢复协程
    err := recover()
    // 异常处理
    if err != nil {
      fmt.Println("异常处理 defer recover", err)
    }
  }()
  fmt.Println("开始执行ExceptionCase方法")
  panic("ExceptionCase抛出异常")
  fmt.Println("ExceptionCase方法执行结束")
}
// main.go
package main
import _case "defer_recover_panic/case"
func main() {
  //_case.DeferCase1()
  //_case.DeferCase2()
  //_case.DeferCase3()
  //_case.ExceptionCase()
  _case.FileReadCase()
}

总结


目录
相关文章
|
2月前
|
Go
go基础-14.异常处理
go基础-14.异常处理
|
4月前
|
存储 Go
掌握 Go 语言的 defer 关键字
掌握 Go 语言的 defer 关键字
|
4月前
|
Go
实验深度理解Go中try...catch...的panic、defer、recover用法
文章通过实验代码演示了Go语言中如何使用panic、defer和recover函数来模拟try...catch...的异常处理机制,并详细解释了每个函数的作用和在异常处理中的使用场景。
38 0
|
7月前
|
Go 开发者
Golang深入浅出之-Go语言 defer、panic、recover:异常处理机制
Go语言中的`defer`、`panic`和`recover`提供了一套独特的异常处理方式。`defer`用于延迟函数调用,在返回前执行,常用于资源释放。它遵循后进先出原则。`panic`触发运行时错误,中断函数执行,直到遇到`recover`或程序结束。`recover`在`defer`中捕获`panic`,恢复程序执行。注意避免滥用`defer`影响性能,不应对可处理错误随意使用`panic`,且`recover`不能跨goroutine捕获panic。理解并恰当使用这些机制能提高代码健壮性和稳定性。
159 2
|
7月前
|
Java Go 区块链
【Go语言专栏】Go语言中的延迟执行与defer语句
【4月更文挑战第30天】Go语言的延迟执行与defer语句用于资源释放和错误处理。defer通过关键字定义,函数返回时执行,顺序与定义相反。参数在定义时求值。应用包括资源释放、错误处理、成对操作和函数包装,是Go编程的关键特性。
60 0
|
测试技术 Go
go defer性能测试
在学习中了解到defer相比没有使用defer会消耗部分时间,所以测试了下,使用与不使用defer的性能测试,通过实验,defer影响程序的速度基本可以忽略不计。
969 0
|
11天前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
23 7
|
11天前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
11天前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
88 71
|
10天前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
96 67