Skip to content
鼓励作者:欢迎打赏犒劳

异常处理

go的异常

如果代码有异常的话,一般在defer中写一些处理逻辑。

recover() 的核心作用是:阻止 panic 向上传播,让程序继续执行而不是崩溃退出!!!!!

首先,要明确的是,defer 一定会执行的。那么为什么还要用recover()捕获异常呢?原因就是让程序恢复正常状态,从而不影响后面的流程

go
func main() {
	defer func() {
		log.Println("Recovered from panic:") // 这里只是打印,没有真正恢复
	}()
	fmt.Println("1111")
	divisor := 0
	i := 1 / divisor // 运行时 panic
	fmt.Println(i)
	fmt.Println("3333")
}

结果

text
1111
2025/09/26 21:54:00 Recovered from panic:
panic: runtime error: integer divide by zero

goroutine 1 [running]:
main.main()
	E:/go_ws/demo/main.go:22 +0x6a

要让程序从 panic 中恢复并继续执行,需要在 defer 中调用 recover():

go
func main() {
	defer func() {
		if r := recover(); r != nil {
			log.Printf("Recovered from panic: %v", r)
			// 程序会继续执行,不会退出
		}
	}()
	fmt.Println("1111")
	// 使用变量,避免编译时计算
	divisor := 0
	i := 1 / divisor // 运行时 panic
	fmt.Println(i)
	fmt.Println("3333")
}

结果

text
1111
2025/09/26 21:59:42 Recovered from panic: runtime error: integer divide by zero

最终示例

go
func main() {
	fmt.Println(111)
	main2()
	fmt.Println(222)
}
func main2() {
	fmt.Println("程序开始")

	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("捕获到 panic: %v\n", r)
			fmt.Println("程序已恢复,继续执行...")
		}
		//fmt.Println("异常。。。。")
	}()

	fmt.Println("执行正常操作...")

	// 模拟 panic
	panic("发生严重错误!")

	fmt.Println("这行不会执行") // panic 后的代码不会执行
}

//111
//程序开始
//执行正常操作...
//捕获到 panic: 发生严重错误!
//程序已恢复,继续执行...
//222

log.Fatal

log.Fatal: 用于预期的、无法恢复的错误,希望立即退出程序并记录错误信息

不会走defer函数!!!

go
package main

import (
    "log"
    "os"
)

func main() {
    // 检查文件是否存在
    if _, err := os.Stat("config.json"); err != nil {
        log.Fatal("配置文件不存在:", err)
        // 这之后的代码不会执行
        fmt.Println("这行不会打印")
    }
    
    // 数据库连接失败
    db, err := connectDB()
    if err != nil {
        log.Fatalf("数据库连接失败: %v", err)
    }
    
    log.Println("程序正常启动")
}

如有转载或 CV 的请标注本站原文地址