程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

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

发布于2019-08-11 07:03     阅读(795)     评论(0)     点赞(1)     收藏(4)


6.1.错误

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

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

   自定义错误类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//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无论写到哪里都是最后执行,不用非要把关闭代码写在最后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//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正好可以解决这个问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//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时返回值已经赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//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时修改了返回值内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//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后,终止剩余代码执行,并打印错误栈信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//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还是执行的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//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状态取消

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//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就不会向上传递
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//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() 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//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()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//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下半部分
程序结束

  



所属网站分类: 技术文章 > 博客

作者:787sds

链接:https://www.pythonheidong.com/blog/article/24895/ef1ddb98dfd63fac891c/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

1 0
收藏该文
已收藏

评论内容:(最多支持255个字符)