标题
⭐[golang/坑/超级坑]意外发现一个无法捕获的异常情况
clq
浏览(24) +
2025-01-02 22:04:19 发表
编辑
关键字:
[2025-01-02 22:24:26 最后更新]
⭐[golang/坑/超级坑]意外发现一个无法捕获的异常情况
golang 是以稳定著称。我一直用它的异常机制用得挺好的,似乎从未发现过无法处理的异常会导致它崩溃的。
所以我一直以为 recover() 可以捕获所有的 golang 异常。今天测试内存回收的时候意外发现
runtime.SetFinalizer
这个调用,在对同一指针调用两次时是会异常崩溃的!而且无法用 recover 捕获!!
妈呀!
不知道是不是我用错了,有没有哪位网友能详细解释原因的。⭐
错误提示为
fatal error: runtime.SetFinalizer: finalizer already set
--------------------------------------------------------
直接调用 runtime.SetFinalizer 两次是不正确的,会导致 fatal error: runtime.SetFinalizer: finalizer already set 错误。
如果你需要修改一个对象的终结器,你应该先调用 runtime.SetFinalizer 将终结器设置为 nil,然后再设置新的终结器。这是正确的做法。
--
也就是说,最安全的办法是,使用前都先设置为 nil 先,这样就不会异常了。
那么还有哪些异常无法用 recover 捕获呢? 下面是一个,应该还有别的。所以大家写程序还是要注意,不能全依靠语言特性本身的。
--------------------------------------------------------
https://www.jianshu.com/p/e2a5a56d148f
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println("在for循环中多次调用调用 t1 := <-timer1.C 引发异常:", err)
}
}()
timer1 := time.NewTimer(time.Millisecond)
for i := 0; i < 2; i++ {
t1 := <-timer1.C // 第二次执行到这里程序会异常中断,不会被defer捕捉,
// 因为严格来说这不是异常,而是 fatal error: all goroutines are asleep - deadlock!
// 因为 timer1.C 是一个 <-chan Time 类型的管道,该管道在触发一次后会被置为nil,此时读取它的值会发生阻塞
// 所以会发生deadlock
// 如果是多协程的话, 如果主协程要等待该协程的话,也会发生deadlock,否则只是该协程不会执行完成,不会引发异常
// 综上, defer不能捕捉该 "异常" , 因为这不是异常,而是程序逻辑错误
fmt.Printf("t1:%v\n", t1)
}
}
NEWBT官方QQ群1: 276678893
可求档连环画,漫画;询问文本处理大师等软件使用技巧;求档softhub软件下载及使用技巧.
但不可"开车",严禁国家敏感话题,不可求档涉及版权的文档软件.
验证问题说明申请入群原因即可.