← 返回目录

defer底层原理

第 22 / 29 卷日期:

goroutine,解除阻塞,以使它去争取继续运行代码的机会。如此阻塞代码也是为了实现操作的互斥和元素值的完整。

扩展

  1. 发送操作和接收操作在什么时候可能会被长时间阻塞?

对于缓冲通道来说,如果通道已满,则对它的所有发送操作都将被阻塞,直到通道中有元素值被接收走,此时通道会通知阻塞队列的首个goroutine,通知顺序是公平的

相对的,如果通道已空,那么对它的所有接收操作会被阻塞,直到通道中有新的元素值出现。

对于非缓冲通道,无论是发送还是接收操作,一开始执行就会被阻塞,直到配对的操作也开始执行,才会继续。可以说非缓冲通道就是在用同步的方式传递数据。且用非缓冲通道时,数据并不会用通道作中转。

如果错误操作也会造成长时间阻塞,最典型的就是对值为nil(即未初始化)的通道进行操作。

  1. 发送操作和接收操作什么时候会引发panic?

对一个已经关闭的通道做发送操作会引发panic,但对已经关闭的通道可以进行接收操作

对一个已经关闭的通道进行关闭操作会引发panic。

defer底层原理

1、每次defer语句在执行的时候,都会将函数进行"压栈",函数参数会被拷贝下来。当外层函数退出时,defer函数会按照定义的顺序逆序执行。如果defer执行的函数为nil,那么会在最终调用函数中产生panic。

2、为什么defer要按照定义的顺序逆序执行

后面定义的函数可能会依赖前面的资源,所以要先执行。如果前面先执行,释放掉这个依赖,那后面的函数就找不到它的依赖了。

3、defer函数定义时,对外部变量的引用方式有两种

分别是函数参数以及作为闭包引用。

在作为函数参数的时候,在defer定义时就把值传递给defer,并被缓存起来。

如果是作为闭包引用,则会在defer真正调用的时候,根据整个上下文去确定当前的值。

4、defer后面的语句在执行的时候,函数调用的参数会被保存起来,也就是复制一份。

在真正执行的时候,实际上用到的是复制的变量,也就是说,如果这个变量是一个"值类型",那他就和定义的时候是一致的,如果是一个"引用",那么就可能和定义的时候的值不一致

defer配合recover

recover(异常捕获)可以让程序在引发panic的时候不会崩溃退出。

在引发panic的时候,panic会停掉当前正在执行的程序,但是,在这之前,它会有序的执行完当前goroutine的 defer列表中的语句。

全站分卷索引 · 29 卷
  1. 1代码随想录知识星球精华(最强八股文)第五版(Go篇))
  2. 2Go string 和 []byte 的区别
  3. 3数组和切片的区别
  4. 4扩容前后的Slice是一样的吗
  5. 5Go语言map是有序的还是无序的, 为什么
  6. 6go里面的map是并发安全的吗?如何并发安全
  7. 7Go 的错误处理和 Java 的异常处理对比
  8. 8介绍一下panic和recover
  9. 9什么是defer?有什么作用
  10. 10Go并发
  11. 11进程、线程的区别
  12. 12什么是go runtine
  13. 13Go语言中的Channel是什么, 有哪些用途,如何处理阻塞
  14. 14什么是互斥锁(mutex)?在什么情况下会用到它们?
  15. 15Mutex有几种模式
  16. 16goroutine什么情况会发生内存泄漏?如何避免。
  17. 17Go语言中GC的流程是什么
  18. 18Go 中的内存逃逸现象是什么?
  19. 19CAP 理论,为什么不能同时满足
  20. 20说一下 Gin 的路由怎么实现的
  21. 21简述slice的底层原理,和数组的区别是什么
  22. 22defer底层原理
  23. 23侵入式和非侵入式的区别
  24. 24goroutine与线程的区别
  25. 25goroutine在什么情况下会被挂起呢?
  26. 26GC(垃圾回收)原理 1.5版本
  27. 27简述Go的垃圾回收机制
  28. 28协程优势及其通信方式
  29. 29Go的内存对齐