V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
dzdh
V2EX  ›  Go 编程语言

苦于没有异常,怎么优雅的捕捉三方包里的 panic

  •  
  •   dzdh · 2022-05-05 18:13:16 +08:00 · 2449 次点击
    这是一个创建于 933 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如有个三方包

    package third
    
    func X() {
        panic("error")
    }
    

    然后我调用

    package main
    
    import third
    
    func main() {
        callX()
    }
    
    func callX() error {
        //thrid.X() 这里会 panic ,怎么拿到当做 error 返回
    }
    
    17 条回复    2022-05-14 15:00:25 +08:00
    jybox
        1
    jybox  
       2022-05-05 18:30:56 +08:00
    undeflife
        2
    undeflife  
       2022-05-05 19:00:51 +08:00
    bugfan
        3
    bugfan  
       2022-05-05 22:23:32 +08:00 via iPhone
    可以看看 gin 框架是怎么捕获的~
    dzdh
        4
    dzdh  
    OP
       2022-05-05 22:26:47 +08:00
    @jybox
    @undeflife

    recover 只能在 defer 里,但是 defer 又没有返回值,怎么能在 callX 方法里把 panic 信息当做 error 返回呢?
    phpfpm
        5
    phpfpm  
       2022-05-05 22:33:22 +08:00
    @dzdh 再包装一层函数啊。。。
    Akkuman
        6
    Akkuman  
       2022-05-05 22:37:06 +08:00 via Android
    @dzdh 先定义一个 err ,再进行 defer func 里面 recover ,如果有 panic 就赋值到 err 上去,然后函数 return 就会带上你的 err 了
    tairan2006
        7
    tairan2006  
       2022-05-05 22:43:03 +08:00 via Android
    panic 的条件你在外围先判断一次不就完了…
    dzdh
        8
    dzdh  
    OP
       2022-05-05 22:51:08 +08:00
    @phpfpm
    @Akkuman
    @tairan2006


    一定要

    ```go
    func call() (err error) {

    defer func() {
    if r := recover(); r != nil {
    err = errors.New(fmt.Sprint(r))
    }
    }()

    err = errors.New("33")

    panic(111)

    return
    }
    ```

    有没有什么语法糖可以 `defer xx()` 就能实现的,或者有什么全局的『拦截器』之类的吗?
    dzdh
        9
    dzdh  
    OP
       2022-05-05 23:04:53 +08:00
    @bugfan

    感觉还不一样。gin 是一次请求中的所有『异常』全部都在某一个点进行『捕获』。但是需要的是在某个特定的业务逻辑中需要捕获某个三方包的异常,如果这个三方包异常了,我要做一些处理,然后业务逻辑继续。

    打个比方说,cli 场景下,进行视频转码,转码失败了,业务还继续,标记转码结果为 fail
    icexin
        10
    icexin  
       2022-05-05 23:27:36 +08:00
    用闭包+工具函数可以达成你的需求 https://gist.github.com/icexin/fd39098dbd8e411d035573d893a46c33
    tairan2006
        11
    tairan2006  
       2022-05-05 23:35:33 +08:00 via Android
    lo.Try

    不过要 1.18
    soseek
        12
    soseek  
       2022-05-06 00:59:37 +08:00 via Android
    ```go
    import "github.com/sohaha/zlsgo/zerror"

    err := zerror.TryCatch(func() error {

    // code

    return nil
    })

    // 如果 TryCatch 内返回了 error 或触发了 panic
    if err != nil{
    // ..
    }

    ```
    joesonw
        13
    joesonw  
       2022-05-06 09:18:41 +08:00 via iPhone
    defer xx(&err) 传指针。
    dzdh
        14
    dzdh  
    OP
       2022-05-06 10:33:11 +08:00
    Juszoe
        15
    Juszoe  
       2022-05-06 10:40:45 +08:00
    lo 是泛型工具库 https://github.com/samber/lo
    dzdh
        16
    dzdh  
    OP
       2022-05-06 13:28:34 +08:00
    @Juszoe 可是只能返回 error ,如果没发生 Panic 的时候,咋获取正确的返回值咧
    Akkuman
        17
    Akkuman  
       2022-05-14 15:00:25 +08:00 via Android
    @dzdh uber 好像有个工具,使用 ast 自动加上,需要用 go generate
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1044 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 19:31 · PVG 03:31 · LAX 11:31 · JFK 14:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.