专栏首页有趣的django6.Go-错误,defer,panic和recover

6.Go-错误,defer,panic和recover

6.1.错误

   Go语言中使用builtin包下error接口作为错误类型

   Go语言中错误都作为方法/函数的返回值

   自定义错误类型

//Learn_Go/main.go
package main

import (
	"errors"
	"fmt"
)

func demo(i,k int) (r int, e error)  {
	if k == 0 {
		e = errors.New("除数不能为0")
		return
	}
	r = i/k
	return
}

func main()  {
	//result,error := demo(6,3)
	result,e := demo(6,0)
	if e != nil{
		fmt.Println("执行错误,错误信息为:",e)   //执行错误,错误信息为: 除数不能为0
		return
	}
	fmt.Println("执行成功,结果:",result)      //执行成功,结果: 2
}

6.2.defer

  Go语言中defer可以完成延迟功能,当前函数执行完成后执行defer功能

  defer最常用的就是关闭连接(数据库,文件等),可以打开连接后紧跟defer进行关闭

(1)Go语言中defer无论写到哪里都是最后执行,不用非要把关闭代码写在最后

//Learn_Go/main.go
package main

import "fmt"

func main()  {
	fmt.Println("打开连接")
	//defer fmt.Println("关闭连接") 
	defer func() {
		fmt.Println("关闭连接")       //defer执行
	}()
	fmt.Println("进行操作")
}

//结果
打开连接
进行操作
关闭连接

(2)多个defer

  多重defer采用栈结构执行,先产生后执行

  在很多代码结构中都可能出现产生多个对象,而程序希望这些对象倒叙关闭,多个defer正好可以解决这个问题

//Learn_Go/main.go
package main

import "fmt"

func main()  {
	fmt.Println("打开连接A")
	defer fmt.Println("关闭连接A")
	fmt.Println("打开连接B")
	defer fmt.Println("关闭连接B")
	fmt.Println("打开连接C")
	defer fmt.Println("关闭连接C")
	fmt.Println("进行操作")
}

//结果
打开连接A
打开连接B
打开连接C
进行操作
关闭连接C
关闭连接B
关闭连接A

(3)defer和return结合

   defer与return同时存在时,要把return理解成两条执行结合,一个指令是给返回值

   赋值,另一个指令返回跳出函数

   defer和return时整体执行顺序

  • 先给返回值赋值
  • 执行defer
  • 返回跳出函数

(4)没有定义返回值接收变量,执行defer时返回值已经赋值

//Learn_Go/main.go
package main

import "fmt"

func demo() int {
	i := 1
	defer func() {
		i = i + 2
	}()
	return i
}

func main() {
	fmt.Println(demo())       //1
}

(5)声明接收返回值变量,执行defer时修改了返回值内容

//Learn_Go/main.go
package main

import "fmt"

func demo() (z int) {
	i := 1
	defer func() {
		z = i + 2
	}()
	return
}

func main() {
	fmt.Println(demo())       //3
}

6.3.panic

panic是build中函数,当执行到panic后,终止剩余代码执行,并打印错误栈信息。

//Learn_Go/main.go
package main

import "fmt"

func main() {
	fmt.Println("111")
	panic("错误信息")
	fmt.Println("222")
}

//结果
111
panic: 错误信息

goroutine 1 [running]:
main.main()
C:/Users/86158/Desktop/Learn_Go/main.go:8 +0x82

panic不是立即停止程序,defer还是执行的

//Learn_Go/main.go
package main

import "fmt"

func main() {
	defer fmt.Println("执行defer的内容")
	fmt.Println("111")
	panic("错误信息")
	fmt.Println("222")
}

//结果
111
执行defer的内容
panic: 错误信息

goroutine 1 [running]:
main.main()
C:/Users/86158/Desktop/Learn_Go/main.go:9 +0xdc

6.4.recover

 recover()表示回复程序的panic(),让程序正常执行

    rcover()是和panic一样都是builtin中函数,可以接受panic的信息,恢复程序的正常执行

    recover()一般在defer内部,如果没有panic信息,返回nil;如果有panic,recover会把panic状态取消

//Learn_Go/main.go
package main

import "fmt"

func main() {
	defer func() {
		if error := recover();error != nil{
			fmt.Println("panic为:", error)
		}
	}()
	fmt.Println("111")
	panic("出现了错误信息")
	fmt.Println("222")
}

//结果
111
panic为: 出现了错误信息

函数调用过程中panic和recover()

  • recover()只能恢复当前函数级或当前函数调用函数中的panic(),恢复后调用当前级别函数结束,但是调用此函数的函数可以继续执行
  • panic会一直向上传递,如果没有recover()则表示程序终止,但是碰见了recover(),recover()所在级别函数表示没有panic,panic就不会向上传递
//Learn_Go/main.go
package main

import "fmt"

func demo1()  {
	fmt.Println("demo1上半部分")
	demo2()
	fmt.Println("demo1下半部分")
}

func demo2()  {
	fmt.Println("demo2上半部分")
	demo3()
	fmt.Println("demo2下半部分")
}

func demo3()  {
	fmt.Println("demo3上半部分")
	panic("demo3中出现panic")
	fmt.Println("demo3下半部分")
}

func main() {
	fmt.Println("程序开始")
	demo1()
	fmt.Println("程序结束")
}

//结果
程序开始
demo1上半部分
demo2上半部分
demo3上半部分
panic: demo3中出现panic

 demo3添加recover() 

//Learn_Go/main.go
package main

import "fmt"

func demo1()  {
	fmt.Println("demo1上半部分")
	demo2()
	fmt.Println("demo1下半部分")
}

func demo2()  {
	fmt.Println("demo2上半部分")
	demo3()
	fmt.Println("demo2下半部分")
}

func demo3()  {
	defer func() {
		recover()
	}()
	fmt.Println("demo3上半部分")
	panic("demo3中出现panic")
	fmt.Println("demo3下半部分")
}

func main() {
	fmt.Println("程序开始")
	demo1()
	fmt.Println("程序结束")
}

//结果
程序开始
demo1上半部分
demo2上半部分
demo3上半部分
demo2下半部分
demo1下半部分
程序结束

 demo2添加recover()

//Learn_Go/main.go
package main

import "fmt"

func demo1()  {
	fmt.Println("demo1上半部分")
	demo2()
	fmt.Println("demo1下半部分")
}

func demo2()  {
	defer func() {
		recover()
	}()
	fmt.Println("demo2上半部分")
	demo3()
	fmt.Println("demo2下半部分")
}

func demo3()  {
	fmt.Println("demo3上半部分")
	panic("demo3中出现panic")
	fmt.Println("demo3下半部分")
}

func main() {
	fmt.Println("程序开始")
	demo1()
	fmt.Println("程序结束")
}

//结果
程序开始
demo1上半部分
demo2上半部分
demo3上半部分
demo1下半部分
程序结束

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Golang学习笔记之错误处理error、panic (抛出错误),recover(捕获错误)

    错误表示程序中出现了异常情况。Go 语言通过内置的错误接口提供了非常简单的错误处理机制。

    李海彬
  • Golang 语言怎么使用 panic 函数?

    panic 是一个 Go 内置函数,它用来停止当前常规控制流并启动 panicking(运行时恐慌)过程。当函数 F 调用 panic 函数时,函数 F 的执行...

    frank.
  • Go 专栏|错误处理:defer,panic 和 recover

    最近校招又开始了,我也接到了一些面试工作,当我问「你觉得自己有什么优势」时,十个人里有八个的回答里会有一条「精力充沛,能加班」。

    AlwaysBeta
  • Go语言学习之 panic 和 recover

    在 Go 语言中,虽然类型系统会捕获许多编译时错误。但是有些错误需要在运行时进行检查,例如数组越界访问。当 Go 语言在运行时检查到这些错误,它就会宕机。

    frank.
  • Go 语言错误及异常处理篇(三):panic 和 recover

    前面学院君介绍了 Go 语言通过 error 接口统一进行错误处理,但这些错误都是我们在编写代码时就已经预见并返回的,对于某些运行时错误,比如数组越界、除数为0...

    学院君
  • Go语言错误与异常处理机制

    1 Error接口 Go语言中的error类型实际上是抽象了Error()方法的error接口

    李海彬
  • Go panic & recover

    之前针对于go 的错误和异常做了简单的介绍,对于panic介绍的不算多,本篇从原理和源码的角度来看一下panic 和 recover是怎么运作的。 panic...

    邹志全
  • Go语言之panic和recover

    panic是Go语言中,用于终止程序的一种函数,往往用在下面两种情况:1)程序出现了很大的故障,例如不能在提供服务了。2)程序在运行阶段碰到了内存异常的操作,例...

    灰子学技术
  • Go语言错误处理

    错误指的是可能出现问题的地方出现了问题,比如打开一个文件时可能失败,这种情况在人们的意料之中。

    Steve Wang
  • defer, panic和recover用法【Golang 入门系列十四】

    以前讲过golang 的基本语法。但是,只是讲了一些基础的语法,感兴趣的可以看看以前的文章,https://www.cnblogs.com/zhangweizh...

    架构师精进
  • panic 和 recover

    在 Go 语言中,程序中一般是使用错误来处理异常情况。对于程序中出现的大部分异常情况,错误就已经够用了。

    酷走天涯
  • Go编写好的错误处理

    假设现在有个需求,返回的值是太小了还是太大了,返回不同的错误,最简单的方法直接改造GetFibonacci:

    gaobinzhan
  • Go语言常见的坑

    这里列举的Go语言常见坑都是符合Go语言语法的,可以正常的编译,但是可能是运行结果错误,或者是有资源泄漏的风险。

    冬夜先生
  • [日常] Go语言圣经-Panic异常,Recover捕获异常习题

    Go语言圣经-Panic异常 1.当panic异常发生时,程序会中断运行,并立即执行在该goroutine中被延迟的函数(defer 机制) 2.不是所有的pa...

    陶士涵
  • Go通关07:错误处理,如何通过error/panic处理错误?

    在Go语言中,错误是通过内置的error接口来表示的,它只有一个Error方法来返回错误信息:

    微客鸟窝
  • <Go语言学习笔记>【异常处理】

    通常 panic 和 recover 是用来处理异常问题的。我们来综述下,他们各自的特点:

    秦穆之
  • 再读Golang中的异常处理 顶

    注意:如果一个没有recover的goroutine发生了panic,那么整个进程都会挂掉

    BGBiao
  • Defer,Panic,and Recover

    Go拥有一般的控制流程机制,像if、for、switch、goto。除此之外go也拥有一个单独的goroutine机制运行go语句。这里我想讨论一些不太常见的语...

    陌无崖
  • 深入Go的错误处理机制(一)使用

    程序运行过程中不可避免的发生各种错误,要想让自己的程序保持较高的健壮性,那么异常,错误处理是需要考虑周全的,每个编程语言提供了一套自己的异常错误处理机制,在Go...

    阿伟

扫码关注云+社区

领取腾讯云代金券