• 【看球和学Go】错误和异常、CGO、fallthrough


    这篇文章将详解「Go必知必会」的知识点:

    1. 错误和异常的对比、发生panic后如何执行代码?会执行到defer代码段吗?
    2. CGO是什么?CGO的作用是什么?
    3. switch中的fallthrough

    错误&异常

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

    异常指的是不应该出现问题的地方出现了问题,比如引用了空指针,这种情况在人们的意料之外。

    可见,错误是业务过程的一部分,而异常不是 。

    处理错误:error

    Golang中引入error接口类型作为错误处理的标准模式,如果函数要返回错误,则返回值类型列表中肯定包含error。error处理过程类似于C语言中的错误码,可逐层返回,直到被处理。

    处理异常:panic&recover

    Golang中引入两个内置函数panic和recover来触发和终止异常处理流程,同时引入关键字defer来延迟执行defer后面的函数。

    panic&defer

    当数组越界、访问非法空间或者我们直接调用panic时,panic会停掉当前正在执行的程序,包括所有协程,比起exit直接退出,panic的退出更有秩序,他会先处理完当前goroutine已经defer挂上去的任务,执行完毕后再退出整个程序。

    而defer的存在,让我们有更多的选择,比如在defer中通过recover截取panic,从而达到try…catch的效果

    panic还可以接收一个参数,通常是字符串类型错误信息,执行到panic时,他会打印这个字符串和触发他的调用栈。

    当然,我们在写代码时要注意,不是所有的异常都能被捕获到的,像fatal error 和runtime.throw 都是不能被recover的

    defer执行顺序

    你可以在一个函数中执行多条defer语句,它们的执行顺序与声明顺序相反:最早声明的defer最后执行。

    总结

    当程序运行时,如果遇到引用空指针、下标越界或显式调用panic函数等情况,则先触发panic函数的执行,然后调用延迟函数。调用者继续传递panic,因此该过程一直在调用栈中重复发生:函数停止执行,调用延迟执行函数等。如果一路在延迟函数中没有recover函数的调用,则会到达该协程的起点,该协程结束,然后终止其他所有协程,包括主协程(类似于C语言中的主线程,该协程ID为1)。

    对比Java、C++

    错误和异常从Golang机制上讲,就是error和panic的区别。很多其他语言也一样,比如C++/Java,没有error但有errno,没有panic但有throw。

    错误异常互相转换

    Golang错误和异常是可以互相转换的:

    1. 错误转异常,比如程序逻辑上尝试请求某个URL,最多尝试三次,尝试三次的过程中请求失败是错误,尝试完第三次还不成功的话,失败就被提升为异常了。
    2. 异常转错误,比如panic触发的异常被recover恢复后,将返回值中error类型的变量进行赋值,以便上层函数继续走错误处理流程

    CGO

    CGO是调用C代码模块,静态库和动态库。

    CGO是C语言和Go语言之间的桥梁,原则上无法直接支持C++的类。CGO不支持C++语法的根本原因是C++至今为止还没有一个二进制接口规范(ABI)。

    CGO只支持C语言中值类型的数据类型,所以我们是无法直接使用C++的引用参数等特性的。

    fallthrough

    在一个 switch 块内,每个 case 无需声明 break 来终止,如果想顺序执行使用fallthrough

    如果我们想强制执行满足条件case的后一个case,也可以通过设置fallthrough的方式:

    代码示例

    package main
    
    import "fmt"
    
    func main() {
        switch {
        case false:
                fmt.Println("false1")
                fallthrough
        case true:
                fmt.Println("true1")
                fallthrough
        case false:
                fmt.Println("false2")
                fallthrough
        case true:
                fmt.Println("true2")
        case false:
                fmt.Println("false3")
                fallthrough
        default:
                fmt.Println("default case")
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    思考一下上面代码的执行结果是什么?

    执行结果

    注意:在switch块内,都建议包含一个 default 语句并且放在最后,即使它什么代码也没有。

    延伸知识点:在select块中,default能避免死锁问题。

    总结

    我们来总结一下:

    1. 在一个 switch 块内,每个 case 无需声明 break 来终止,如果想顺序执行使用fallthrough;如果我们想强制执行满足条件case的后一个case,也可以通过设置fallthrough的方式。
    2. CGO是调用C代码模块,静态库和动态库。CGO只支持C语言中值类型的数据类型,所以我们是无法直接使用C++的引用参数等特性的。
    3. 当程序运行时,如果遇到引用空指针、下标越界或显式调用panic函数等情况,则先触发panic函数的执行,然后调用延迟函数。调用者继续传递panic,因此该过程一直在调用栈中重复发生:函数停止执行,调用延迟执行函数等。如果一路在延迟函数中没有recover函数的调用,则会到达该协程的起点,该协程结束,然后终止其他所有协程,包括主协程(类似于C语言中的主线程,该协程ID为1)。

    一起学习

    如果你觉得这期内容不错的话,一定要三连支持一波。

    下方有我的公众号卡片,欢迎扫码关注,领取免费硬核的编程资料。

  • 相关阅读:
    C# xml序列化以及遇到的坑
    Docker常用命令
    Intellij IDEA--修改JDK版本
    小程序商城上线需要做什么?
    快速入门XPath语法,轻松解析爬虫时的HTML内容
    live555 音视频处理相关文档解读,
    详解如何在数仓中搭建细粒度容灾应用
    树控件、下拉框、文本框常用测试用例
    设计模式总结
    Workerman开启ssl方法如下
  • 原文地址:https://blog.csdn.net/w425772719/article/details/128033874