首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
宝塔
V2EX  ›  程序员

golang 1.13 errors 包来了,不用写“err 气功波”代码

  •  
  •   guonaihong · 37 天前 · 3137 次点击
    这是一个创建于 37 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这篇是对 errors 包 的姿势挖掘

    气功波错误代码

    从 http.Get()返回的错误 判断 syscall.ECONNREFUSED 错误.以前要对 go 标准库 error 结构有点熟悉,才能写出下面的代码

    func CmdErr(err error) {
        if err == nil {
            return
        }   
    
        if uerr, ok := err.(*url.Error); ok {
            if noerr, ok := uerr.Err.(*net.OpError); ok {
                if scerr, ok := noerr.Err.(*os.SyscallError); ok {
                    if scerr.Err == syscall.ECONNREFUSED {
                        fmt.Printf("gurl: (7) couldn't connect to host\n")
                        return
                    }
                }
            }
        }   
    
        fmt.Printf("%s\n", err)
    }
    
    

    用 go1.13 errors 库重构气功波代码

    现在只要知道,syscall.ECONNREFUSED 就行。先用 Unwrap 不停的解包 error。最后可能得到需要的 err

    func newCmdErr(err error) {
        for {
            err = errors.Unwrap(err)
            if err == nil {
                break
            }
    
            if err == syscall.ECONNREFUSED {
                fmt.Printf("gurl: (7) couldn't connect to host\n")
                return
            }
        }
    }
    
    
    

    交流学习

    一起挖掘 errors 包的用法

    github

    https://github.com/guonaihong/gout

    第 1 条附言  ·  37 天前

    // 这是代码量最少的写法。

    func newCmdErr2(err error) {
    
        if errors.Is(err, syscall.ECONNREFUSED) {
            fmt.Printf("gurl: (7) couldn't connect to host\n")
            return
        }   
    }
    
    20 回复  |  直到 2019-10-15 08:15:25 +08:00
        1
    rootxigua   37 天前
    那如果 err 不为空,并且不等于 syscall.ECONNREFUSED,这个循环会结束吗?
        2
    edussx   37 天前
    @rootxigua 这种情况下 errors.Unwrap(err)这行会一直跑,直到返回 nil,然后在下面 break 跳出循环

    具体参考这个方法的实现: https://golang.org/src/errors/wrap.go?s=372:400#L4
        3
    lizhenda   37 天前
    看起来写法不错,更易读了
        4
    rootxigua   37 天前
    @edussx 懂了。源码很清晰,谢谢
        5
    reus   37 天前   ♥ 3
    难道不是 errors.Is(err, syscall.ECONNREFUSED) 就行了?
        6
    iugo   37 天前
    还是觉得 Go 的错误处理是个值得商榷的点.
        7
    Hanggi   37 天前
    这个代码本来就不用写什么气功波吧?有谁会这么写吗?
        8
    guonaihong   37 天前
    @reus 是的,这是最优解。
        9
    boyhailong   37 天前
    气功波? 返回值不想处理可以忽略的
        10
    guonaihong   37 天前
    @boyhailong 这里的用法是,如果是 syscall.ECONNREFUSED 的错误打印 提示信息。所以就不能忽略。。。
        11
    guonaihong   37 天前
    @iugo 是的,现在比较大的痛点有

    ``` go
    fd, err := os.Open("文件")
    if err != nil {
    return err
    }
    ```
    如果 go 里面有语法糖,在语句结尾加个符号,生成 if err != nil { return err}的代码就好了。比如下面的伪代码.
    fd, err := os.Open("文件“) ?
        12
    ChristopherWu   36 天前
    实不相瞒,我看不懂这代码在搞啥子
    ```
    func CmdErr(err error) {
    if err == nil {
    return
    }

    if uerr, ok := err.(*url.Error); ok {
    if noerr, ok := uerr.Err.(*net.OpError); ok {
    if scerr, ok := noerr.Err.(*os.SyscallError); ok {
    if scerr.Err == syscall.ECONNREFUSED {
    fmt.Printf("gurl: (7) couldn't connect to host\n")
    return
    }
    }
    }
    }

    fmt.Printf("%s\n", err)
    }
    ```
        13
    guonaihong   36 天前
    @ChristopherWu 查询 err 看是否包含 syscall.ECONNREFUSED 这种情况。go1.13 以前只能这么干。。
        14
    Nitroethane   36 天前 via Android
    @guonaihong 这不就是 rust 中的语法么...
        15
    guonaihong   36 天前
    @Nitroethane 对的,伪代码符号参考的 rust ?号,go 现在没有,有就好了。
        16
    EscYezi   36 天前 via iPhone
    不停的 unwrap 怎么看起来像在手动完成 java 的 printStackTrace......
        17
    guonaihong   36 天前
    @EscYezi 没玩过 java。。。
        18
    mason961125   36 天前
    这样写,我觉得 https://github.com/hashicorp/errwrap 更好
        19
    guonaihong   36 天前
    @mason961125 谢了,我明天玩下。
        20
    zjh6   36 天前
    气功波,是搞笑.
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4210 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 26ms · UTC 07:38 · PVG 15:38 · LAX 23:38 · JFK 02:38
    ♥ Do have faith in what you're doing.