惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Latest
Security Latest
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
N
Netflix TechBlog - Medium
GbyAI
GbyAI
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
宝玉的分享
宝玉的分享
博客园 - 【当耐特】
C
Cyber Attacks, Cyber Crime and Cyber Security
雷峰网
雷峰网
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Threat Research - Cisco Blogs
NISL@THU
NISL@THU
Spread Privacy
Spread Privacy
P
Proofpoint News Feed
J
Java Code Geeks
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
MyScale Blog
MyScale Blog
T
Tor Project blog
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
P
Privacy & Cybersecurity Law Blog
MongoDB | Blog
MongoDB | Blog
Simon Willison's Weblog
Simon Willison's Weblog
C
Cybersecurity and Infrastructure Security Agency CISA
L
LINUX DO - 热门话题
小众软件
小众软件
G
GRAHAM CLULEY
P
Privacy International News Feed
AWS News Blog
AWS News Blog
Know Your Adversary
Know Your Adversary
P
Palo Alto Networks Blog
人人都是产品经理
人人都是产品经理
S
Schneier on Security
Scott Helme
Scott Helme
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog RSS Feed
T
The Exploit Database - CXSecurity.com
Recent Announcements
Recent Announcements
E
Exploit-DB.com RSS Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
U
Unit 42
The Register - Security
The Register - Security
S
Securelist
Martin Fowler
Martin Fowler
Project Zero
Project Zero
大猫的无限游戏
大猫的无限游戏
Cisco Talos Blog
Cisco Talos Blog

博客园 - 自然洒脱

MiniMax 权益码 Token Plan 套餐 9 折优惠 go语言context包 go语言通道 go语言GMP模型 go语言mongodb操作 go语言gorm的CRUD go语言gorm go语言mysql驱动 go语言log相关 go语言包管理 go语言时间相关 go语言序列化和反序列化 go语言的"面向对象" go语言结构体排序 go语言接口 go语言结构体(二) go语言结构体(一) go语言递归函数及defer go语言函数作用域及匿名函数
go语言异常处理
自然洒脱 · 2023-07-04 · via 博客园 - 自然洒脱

异常处理

Go的设计者认为其它语言异常处理太过消耗资源,且设计和处理复杂,导致使用者不能很好的处理错误,甚至觉得异常和错误处理起来麻烦而被忽视、忽略掉,从而导致程序崩溃。 为了解决这些问题,Go将错误处理设计的非常简单

  • 函数调用,返回值可以返回多值,一般最后一个值可以是error接口类型的值
  1. 如果函数调用产生错误,则这个值是一个error接口类型的错误
  2. 如果函数调用成功,则该值是nil
  • 检查函数返回值中的错误是否是nil,如果不是nil,进行必要的错误处理

 error是Go中声明的接口类型

type error interface {
    Error() string
}

 所有实现 Error() string 签名的方法,都可以实现错误接口。用Error()方法返回错误的具体描述。

package main

import (
    "fmt"
)

type Myerr struct {
    s string
}

// error接口中只有一个方法,因此实现了error接口
func (p *Myerr) Error() string {
    return p.s
}

// 构造实例,返回指针类型,也可以是*error
func NewMyerr(t string) *Myerr {
    return &Myerr{t}
}

func div(a, b int) (int, error) {
    if b == 0 {
        return 0, NewMyerr("除零异常")
    }
    return a / b, nil
}

func main() {
    err := NewMyerr("自定义error")
    fmt.Printf("%#v\n", err)
    fmt.Println(err.Error())
    var e1 error = err
    fmt.Printf("%#v\n", e1)
    fmt.Println(div(5, 0))
}

示例

下面是上面代码的返回:

 panic

panic发生时,往往会造成程序崩溃、服务终止等后果,所以没人希望它发生。但是, 如果在错误发生时,不及时panic而终止程序运行,继续运行程序恐怕造成更大的损失,付出更加惨痛的 代价。所以,有时候,panic导致的程序崩溃实际上可以及时止损,只能两害相权取其轻。 panic虽然不好,体验很差,但也是万不得已,可以马上暴露问题,及时发现和纠正问题。

panic产生

  • runtime运行时错误导致抛出panic,比如数组越界、除零
  • 主动手动调用panic(reason),这个reason可以是任意类型

panic执行

  • 逆序执行当前已经注册过的goroutine的defer链(recover从这里介入)
  • 打印错误信息和调用堆栈
  • 调用exit(2)结束整个进程

recover

recover即恢复,defer和recover结合起来,在defer中调用recover来实现对错误的捕获和恢复,让代码 在发生panic后通过处理能够继续运行。类似其它语言中try/catch。

err := recover() , v := err.(type) ,v就是 panic(reason) 中的reason,reason可以是任意类 型。

func div(a, b int) int {
    defer func() {
        err := recover()
        fmt.Printf("%T %[1]v\n", err)
        switch v := err.(type) {
        case string:
            fmt.Println("字符串", v)
        case runtime.Error:
            fmt.Printf("%T %[1]v\n", v)
        }
    }()
    r := a / b
    return r
}

func main() {
    fmt.Println(div(5, 0))
}

打印结果:

 一旦在某函数中panic,当前函数panic之后的语句将不再执行,开始执行defer。如果在defer 中错误被recover后,就相当于当前函数产生的错误得到了处理。当前函数执行完defer,当前函数退出 执行,程序还可以从当前函数之后继续执行。

有panic,一路向外抛出,但没有一处进行recover,也就是说没有地方处理错误,程序崩溃

有painc,有recover来捕获,相当于错误被处理掉了,当前函数defer执行完后,退出当前函数, 从当前函数之后继续执行。