章工运维 章工运维
首页
  • linux
  • windows
  • 中间件
  • 监控
  • 网络
  • 存储
  • 安全
  • 防火墙
  • 数据库
  • 系统
  • docker
  • 运维工具
  • other
  • elk
  • K8S
  • ansible
  • Jenkins
  • GitLabCI_CD
  • 随笔
  • 面试
  • 工具
  • 收藏夹
  • Shell
  • python
  • golang
友链
  • 索引

    • 分类
    • 标签
    • 归档
    • 首页 (opens new window)
    • 关于我 (opens new window)
    • 图床 (opens new window)
    • 评论 (opens new window)
    • 导航栏 (opens new window)
周刊
GitHub (opens new window)

章工运维

业精于勤,荒于嬉
首页
  • linux
  • windows
  • 中间件
  • 监控
  • 网络
  • 存储
  • 安全
  • 防火墙
  • 数据库
  • 系统
  • docker
  • 运维工具
  • other
  • elk
  • K8S
  • ansible
  • Jenkins
  • GitLabCI_CD
  • 随笔
  • 面试
  • 工具
  • 收藏夹
  • Shell
  • python
  • golang
友链
  • 索引

    • 分类
    • 标签
    • 归档
    • 首页 (opens new window)
    • 关于我 (opens new window)
    • 图床 (opens new window)
    • 评论 (opens new window)
    • 导航栏 (opens new window)
周刊
GitHub (opens new window)
  • python

  • shell

  • go

    • go基础

      • 指针
      • 数组
      • 切片
      • 字典
      • 结构体
      • 匿名组合
      • 方法
      • 接口
      • error接口
      • panic使用
      • Init函数和main函数
      • 下划线
      • go报错问题收集
      • Redis和MySQL结合的Web服务示例
      • go定义json数据
      • 使用go和vue编写学生管理系统
      • gin框架探索
    • 编程
    • go
    • go基础
    章工运维
    2024-11-21
    目录

    panic使用

    # Go panic 介绍

    在 Go 语言中,panic 是用于引发程序运行时错误的内置函数。调用 panic 会导致程序立即停止正常执行,并进入恐慌状态,执行调用栈中的**延迟函数(defer)**后退出程序。

    panic 通常用于以下场景:

    1. 不可恢复的错误:程序无法继续运行,必须立即停止。
    2. 编程错误:例如数组越界、无效类型断言等。

    # 1. panic 的语法

    panic("error message")
    
    1

    当 panic 被调用时:

    1. 当前函数停止执行。
    2. 延迟(defer)语句会按照调用顺序的逆序执行。
    3. 程序崩溃并打印错误信息,包括调用栈。

    # 2. 使用案例

    # 2.1 简单的 panic 示例

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("Start")
        panic("Something went wrong!")
        fmt.Println("End") // 不会执行
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    输出:

    Start
    panic: Something went wrong!
    
    goroutine 1 [running]:
    main.main()
        /path/to/code.go:6 +0x49
    exit status 2
    
    1
    2
    3
    4
    5
    6
    7
    • 解释:调用 panic 后,fmt.Println("End") 不会执行。

    # 2.2 延迟函数与 panic

    defer 语句在 panic 发生时仍然会被执行,可以用于释放资源、打印日志等操作。

    package main
    
    import "fmt"
    
    func main() {
        defer fmt.Println("Defer 1 executed")
        defer fmt.Println("Defer 2 executed")
    
        fmt.Println("Before panic")
        panic("Something went wrong!")
        fmt.Println("After panic") // 不会执行
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    输出:

    Before panic
    Defer 2 executed
    Defer 1 executed
    panic: Something went wrong!
    
    goroutine 1 [running]:
    main.main()
        /path/to/code.go:9 +0x49
    exit status 2
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    • 解释:defer 的调用顺序是后进先出。

    # 3. 捕获 panic(recover)

    Go 提供了内置函数 recover,用于捕获并处理 panic,避免程序崩溃。

    # 3.1 recover 的基本用法

    recover 只能在延迟函数中调用。如果在延迟函数中捕获到 panic,程序将恢复正常执行。

    package main
    
    import "fmt"
    
    func main() {
        defer func() {
            if r := recover(); r != nil {
                fmt.Println("Recovered from panic:", r)
            }
        }()
    
        fmt.Println("Before panic")
        panic("Something went wrong!")
        fmt.Println("After panic") // 不会执行
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    输出:

    Before panic
    Recovered from panic: Something went wrong!
    
    1
    2

    # 3.2 使用 recover 的实际场景

    1. 保证服务稳定性:在服务端程序中,panic 可能会因为意外导致服务崩溃。可以使用 recover 捕获异常,防止整个服务退出。

    2. 资源清理:在 panic 发生时,使用 recover 捕获错误并完成资源清理。

    # 示例:Web 服务器中使用 recover

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func recoverMiddleware(next http.HandlerFunc) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
            defer func() {
                if err := recover(); err != nil {
                    http.Error(w, "Internal Server Error", http.StatusInternalServerError)
                    fmt.Println("Recovered from panic:", err)
                }
            }()
            next(w, r)
        }
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {
        panic("unexpected error!")
    }
    
    func main() {
        http.HandleFunc("/", recoverMiddleware(handler))
        fmt.Println("Server is running on port 8080")
        http.ListenAndServe(":8080", nil)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    • 解释:
      • 当 handler 中发生 panic 时,recoverMiddleware 会捕获错误并返回 HTTP 500 响应,而不会导致服务器崩溃。

    # 4. panic 和 recover 的实际应用

    # 4.1 自定义错误处理函数

    package main
    
    import (
        "fmt"
    )
    
    func safeExecute(fn func()) {
        defer func() {
            if r := recover(); r != nil {
                fmt.Println("Recovered from panic:", r)
            }
        }()
        fn()
    }
    
    func riskyOperation() {
        panic("critical failure")
    }
    
    func main() {
        fmt.Println("Starting program")
    
        safeExecute(riskyOperation)
    
        fmt.Println("Program continues after recovery")
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    输出:

    Starting program
    Recovered from panic: critical failure
    Program continues after recovery
    
    1
    2
    3

    # 4.2 数据库连接中的 panic 处理

    package main
    
    import (
        "database/sql"
        "fmt"
        _ "github.com/mattn/go-sqlite3"
    )
    
    func connectDatabase() {
        defer func() {
            if r := recover(); r != nil {
                fmt.Println("Recovered from panic during database connection:", r)
            }
        }()
    
        panic("Unable to connect to database")
    }
    
    func main() {
        connectDatabase()
        fmt.Println("Program continues after recovery")
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    输出:

    Recovered from panic during database connection: Unable to connect to database
    Program continues after recovery
    
    1
    2

    # 5. panic 与错误处理的区别

    特点 panic 错误处理 (error)
    使用场景 不可恢复的致命错误,如编程逻辑错误。 可恢复的错误,例如文件未找到、网络错误
    是否终止程序 是(除非使用 recover 捕获)。 否,需显式处理。
    适合场景 仅用于严重错误,或者库内部无法处理的问题。 常见错误处理,推荐的方式。
    灵活性 简单粗暴,直接终止当前函数。 更灵活,可逐步返回错误到调用方。

    # 6. 总结

    • panic 是 Go 中处理不可恢复错误的工具,应谨慎使用。
    • defer 与 recover 搭配可以捕获 panic,从而避免程序崩溃。
    • 实际开发中,panic 常用于:
      • 处理编程中的致命错误。
      • 防止库的错误传播到外部。
    • Go 推荐使用 error 返回值处理常规错误,而非依赖 panic。
    微信 支付宝
    上次更新: 2024/11/21, 10:50:23

    ← error接口 Init函数和main函数→

    最近更新
    01
    shell脚本模块集合
    05-13
    02
    生活小技巧(认知版)
    04-29
    03
    生活小技巧(防骗版)
    04-29
    更多文章>
    Theme by Vdoing | Copyright © 2019-2025 | 点击查看十年之约 | 鄂ICP备2024072800号
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式