V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
d0m2o08

请教一下怎么优雅的处理 go 中的 err

  •  
  •   d0m2o08 · May 24, 2019 · 10543 views
    This topic created in 2534 days ago, the information mentioned may be changed or developed.
    go 中大部分短赋值都会有一个 xx, err :=
    难道要每次都 if err != nil 么
    大佬都是用什么方式处理的?

    func checkErr(err error) {
    if err != nil{
    panic(err)
    }
    }

    这样貌似也很低级啊
    62 replies    2022-08-08 19:21:15 +08:00
    guonaihong
        1
    guonaihong  
       May 24, 2019
    不用 hack 第三库只能这样,或者等 go2.0
    Fule
        2
    Fule  
       May 24, 2019   ❤️ 3
    很久以前研究 GO 的时候,仿佛还说这种 if err != nil 的方式是优点,参数类型放在后面也是优点 …… 我几乎相信了……
    wa8n
        3
    wa8n  
       May 24, 2019
    反正我是写 if err != nil return 写吐了
    lhx2008
        4
    lhx2008  
       May 24, 2019
    这个是真的不方便,try catch finally 被 Go 搞成 err != nil, recover, defer
    araraloren
        5
    araraloren  
       May 24, 2019
    多返回值的滥用。。
    Muninn
        6
    Muninn  
       May 24, 2019
    在 vscode 里打 ife 然后自动补全……
    因为 golang 里概率最大的是返回一个 struct 的指针加 err,所以自动补全的这个也是返回 nil,err
    如果只有一个返回值 err,再按 tab 把 nil 删掉就好了。
    其实也就看起来浪费行数,用起来还是不错的,各种地方都无脑返回,只在最高层统一处理就好了。

    API 的话可以在框架集中处理,参考我这篇文章
    https://zhuanlan.zhihu.com/p/26300634
    dodo2012
        7
    dodo2012  
       May 24, 2019
    if err != nil 是真的太啰嗦,
    Qzier
        8
    Qzier  
       May 24, 2019
    这是所谓的“特性”,无解。
    BCy66drFCvk1Ou87
        9
    BCy66drFCvk1Ou87  
       May 24, 2019
    关键是这种写法
    ````
    if err:= xxx; err != nil {
    //
    }
    ````
    刚开始写 go 的时候很不习惯,跟 for 神似……
    BCy66drFCvk1Ou87
        10
    BCy66drFCvk1Ou87  
       May 24, 2019
    @HuasLeung err := xxx 空格打多了
    freestyle
        11
    freestyle  
       May 24, 2019 via iPhone
    https://imhanjm.com/2018/07/08/go 代码如何优雅地错误处理(error%20handling%20and%20go%201)/
    pmispig
        13
    pmispig  
       May 24, 2019   ❤️ 1
    我现在已经接受了这种写法了,反过来想,C 不是也得判断返回值是否大于 0 吗
    zvall
        14
    zvall  
       May 24, 2019
    趁早放弃 go 吧
    chenset
        15
    chenset  
       May 24, 2019
    Live Templates 缓解一下
    zzn
        16
    zzn  
       May 24, 2019
    错误处理本来就是个大难题, 异常也不见得有好多多少

    但是在 go 里面逢错误就 panic 的写法毫无疑问很低级
    VDimos
        17
    VDimos  
       May 24, 2019 via Android
    和 rust 的 Result 有得一拼
    Vegetable
        18
    Vegetable  
       May 24, 2019
    这个让我想起了地铁的手指口呼.

    https://zh.wikipedia.org/wiki/%E6%8C%87%E5%B7%AE%E7%A2%BA%E8%AA%8D

    这样强迫 coder 显式处理每一个可能出现的错误,可以说是有好处的,可以说现在写输入 ife 已经成了肌肉记忆了 233333
    chenset
        19
    chenset  
       May 24, 2019
    看了下 Go 2 引入了 check & handle https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md#draft-design

    ```

    func CopyFile(src, dst string) error {
    handle err {
    return fmt.Errorf("copy %s %s: %v", src, dst, err)
    }

    r := check os.Open(src)
    defer r.Close()

    w := check os.Create(dst)
    handle err {
    w.Close()
    os.Remove(dst) // (only if a check fails)
    }

    check io.Copy(w, r)
    check w.Close()
    return nil
    }

    ```
    cubecube
        20
    cubecube  
       May 24, 2019 via Android
    异常可以不处理,一直抛啊。
    keysona
        21
    keysona  
       May 24, 2019   ❤️ 1
    习惯就好。

    c 的返回也是这样写的。

    一开始我写 java 的 try catch 也写吐了。

    每个语言都有罗嗦烦人的地方。大部分情况只能你去适应了,不想适应就换语言吧。
    keepeye
        22
    keepeye  
       May 24, 2019
    虽然写的很不爽,但不能否认,这样写出来的程序是比脚本语言写出来的更健壮一些。另外 try ... catch 也不见得有多好
    dabaibai
        23
    dabaibai  
       May 24, 2019
    这种比 try catch 要好,
    写过 10 年 C++的 是这么认为的
    SurfaceView
        24
    SurfaceView  
       May 24, 2019
    @Fule 完全同意,这 2 个点完全是 xxx 的存在,那个 err 我先不评价什么,毕竟是特性, 但是那个类型放后面
    纯粹是为了跟别人不一样 而不一样。
    impl
        25
    impl  
       May 24, 2019 via Android
    用上 rust,只想说没有 nil 和 null 的世界真美好。回去看以前写的 go 代码,一堆 nil 堆的像屎山一样。。
    pmispig
        26
    pmispig  
       May 24, 2019
    @impl 老哥,rust 这么丑陋的语法和一堆符号是怎么克服的,我试了好多次想学,看着看着就想吐了。。
    Kilerd
        27
    Kilerd  
       May 24, 2019
    @pmispig #26 不是我吐槽你,Rust 除了显式生命周期难看一点以外,其他都比 Go 好多了好吗? 而且现在有 Miri 和 NLL 的支持,很少机会能写到显式生命周期了(除非写底层)
    looplj
        28
    looplj  
       May 24, 2019
    跟异常一样,往上抛,调用方处理。
    当然,如果是不能处理的错误,直接 panic 也没问题。
    pmispig
        29
    pmispig  
       May 24, 2019
    @Kilerd 主要是各种符号太多了,看得我脑壳晕
    gamexg
        30
    gamexg  
       May 24, 2019
    用 golang,打 err 自动补全 if,还算可以接受
    Kilerd
        31
    Kilerd  
       May 24, 2019
    @pmispig #29 可能我写习惯了,没发现有什么太多的符号(连 JS 的一半都没有呢)

    || 表示闭包
    ! 表示 宏
    ? 向上抛异常。

    也就这几个比较特殊的
    pmispig
        32
    pmispig  
       May 24, 2019
    @Kilerd
    ```
    client.get(uri).and_then(|res| {
    println!("Response: {}", res.status());

    res.body().for_each(|chunk| {
    io::stdout()
    .write_all(&chunk)
    .map_err(From::from)
    })
    });
    ```
    有种一口气走到底的感觉,有点喘不过气。像以前 js express 那种回调层层嵌套,全是匿名函数的错觉...
    beidounanxizi
        33
    beidounanxizi  
       May 24, 2019
    看看 gopheracdamey 写的系列文章 楼主问的问题 go github wiki 有很多好资料 仔细找找不难发现
    impl
        34
    impl  
       May 24, 2019 via Android
    @pmispig 把 book 看一遍,掌握 struct,enum,match,if let 这些东西先,觉得有意思了再继续深入
    impl
        35
    impl  
       May 24, 2019 via Android
    @pmispig 已经开始支持 async/await,后面不用 and_then 这种写法。romio 了解一下
    ICKelin
        36
    ICKelin  
       May 24, 2019
    我觉得 go 的错误处理写法没啥问题,但是通常我写 go 是基本不会写 panic 和 recover 的。。
    Hellert
        37
    Hellert  
       May 24, 2019
    Go 的错误处理除了啰嗦点,其实没什么大毛病,这点就是继承了 C 语言程序就是输入+输入出的设计,简单。try catch 这种也不是万能的。
    错误处理 Go2 做了优化,应该会少写一些 if。

    其实能和 Go 语言做比较的只有 C,拿其它语言和 Go 比都不是太恰当,比如指针这个概念,大多数现代语言都放弃了,但在 Go 中却是非常核心的东西。
    还有面向对象的那一堆理论,Go 完全没有,怎么去和 Java 这种比较?
    knowckx
        38
    knowckx  
       May 24, 2019
    通过编辑器的 snippets 来自动完成有关错误处理的代码,工作效率会高很多

    if err != nil {
    log.Err("%s", err)
    }
    impl
        39
    impl  
       May 24, 2019 via Android
    rob 想保持 go 简单和地道,现在关于 go 那些改进的方案,rob 说了,可能都不会合到 go2 里面。油管视频
    其实 go 这门语言多年前就死了。go2 可能就是画出来的大饼,什么时候能出来,没人知道。
    loading
        40
    loading  
       May 24, 2019 via Android
    我也有一个 FuckErr()
    zeromake
        41
    zeromake  
       May 24, 2019 via Android
    这些返回错误搞得栈信息全丢了
    auin
        42
    auin  
       May 24, 2019
    既然选择了 Go,那么就用 Go 的方式处理错误,Go 不是一门语法“优雅”的语言
    Nugine0
        43
    Nugine0  
       May 24, 2019 via Android
    @pmispig 问号操作符能缓解,等 async/await 稳定后写异步也能喘气了
    ysc3839
        44
    ysc3839  
       May 24, 2019 via Android
    @pmispig 但是 C 有 #define,可以弄成 CHECK_RETURN(function());
    index90
        45
    index90  
       May 24, 2019
    都说 if err != nil 不好,我想问,你们认为好的是怎样的?
    RubyJack
        46
    RubyJack  
       May 24, 2019
    我从 if err != nil 中学到了很多,原来这个底层调用也可能报错
    WilliamYang
        47
    WilliamYang  
       May 24, 2019
    我已经习惯,并可能喜欢上它了
    Skye347
        48
    Skye347  
       May 24, 2019 via Android   ❤️ 2
    就 Rust 而言,只有错误没有异常,可能出错的地方统一用 Result<Item,Error>代替,不想处理直接往上抛直接打?号,不想处理显示报错直接.unwrap (),不想处理直接忽略有 if let,不想处理带默认值有 unwrap_or(),想处理直接用 match 处理部分或全部情况,再或者结合 map 等函数式风格随意组合,多种方式随意选择,还有 IDE/编译器提示。
    不过 go 选择了类 c 的风格,强调简单,那也没哪个好或者不好的了。
    neoblackcap
        49
    neoblackcap  
       May 24, 2019   ❤️ 4
    @Skye347 就 Result 这个设计就是吸收了多年 PL 研究成果的好东西,配合自带的各种方法,写起代码行云流水。错误能处理的就处理,不能处理就抛给 caller,还能配合编译器进行类型检查,Monad 的应用,这么好的东西有人理解不了,硬说跟 error code 一样,还能说什么。我觉得这些人用 Go 跟 C 都挺好的,记得不要忘记检查错误码就好了
    skadi
        50
    skadi  
       May 24, 2019 via iPhone
    defer
    sunny352787
        51
    sunny352787  
       May 24, 2019
    你们这帮 Java 转 Go 的肯定都喜欢 try,就是习惯
    你看像我们 C++转 Go 的从来不会提这类问题~
    Em5O7B1JGfjQnBry
        52
    Em5O7B1JGfjQnBry  
       May 24, 2019 via Android
    这都能讨论这么多,我的天,不就是个 Monad 随手就能解决的问题么,真是尴尬
    petelin
        53
    petelin  
       May 24, 2019 via iPhone
    你们这些都不看错误怎么处理的人 能写出什么严谨的程序
    zhuangzhuang1988
        54
    zhuangzhuang1988  
       May 24, 2019
    换个语言
    derek80
        55
    derek80  
       May 24, 2019 via iPhone
    @SurfaceView pascal 也是放后面啊,还有 var
    Tyanboot
        56
    Tyanboot  
    PRO
       May 25, 2019 via Android
    @VDimos Rust 的 Result 和 Option 不知道比 go 的 err 高到哪里去了🙃。
    python
        57
    python  
       May 25, 2019 via Android
    习惯成自然
    skiy
        58
    skiy  
       May 25, 2019
    slice[0:100]
    当 100 超出了 len(slice),就报错了,特别烦这个,有解决方案么
    neoblackcap
        59
    neoblackcap  
       May 25, 2019
    @skiy 你为什么需要访问越界的元素?
    Karblue
        60
    Karblue  
       May 25, 2019
    吐槽 err 的几乎是喜欢把所有都错误 try catch 的人,虽然确实很啰嗦,但是这个特性写过 c/c++的人就知道,还是比较方便的.
    更严谨,也更啰嗦,至少更能了解程序内部哪个地方出错了
    guanhui07
        61
    guanhui07  
       Jul 5, 2019
    挺好的 期待 2.0
    gaifanking
        62
    gaifanking  
       Aug 8, 2022
    @Karblue java try catch 有堆栈信息啊,一样能看到哪行错了,把所有代码整个 try catch 完事。go 每一个调用都要写。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2596 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 140ms · UTC 12:46 · PVG 20:46 · LAX 05:46 · JFK 08:46
    ♥ Do have faith in what you're doing.