Golang Go语言中如何优雅的处理 err

发布于 1周前 作者 phonegap100 来自 Go语言

Golang Go语言中如何优雅的处理 err
go 中大部分短赋值都会有一个 xx, err :=
难道要每次都 if err != nil 么
大佬都是用什么方式处理的?

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

这样貌似也很低级啊

63 回复

不用 hack 第三库只能这样,或者等 go2.0

更多关于Golang Go语言中如何优雅的处理 err的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


很久以前研究 GO 的时候,仿佛还说这种 if err != nil 的方式是优点,参数类型放在后面也是优点 …… 我几乎相信了……

反正我是写 if err != nil return 写吐了

这个是真的不方便,try catch finally 被 Go 搞成 err != nil, recover, defer

多返回值的滥用。。

在 vscode 里打 ife 然后自动补全……
因为 golang 里概率最大的是返回一个 struct 的指针加 err,所以自动补全的这个也是返回 nil,err
如果只有一个返回值 err,再按 tab 把 nil 删掉就好了。
其实也就看起来浪费行数,用起来还是不错的,各种地方都无脑返回,只在最高层统一处理就好了。

API 的话可以在框架集中处理,参考我这篇文章
https://zhuanlan.zhihu.com/p/26300634

if err != nil 是真的太啰嗦,

这是所谓的“特性”,无解。

关键是这种写法
<br>if err:= xxx; err != nil {<br> //<br>}<br>
刚开始写 go 的时候很不习惯,跟 for 神似……

err := xxx 空格打多了

https://imhanjm.com/2018/07/08/go 代码如何优雅地错误处理(error%20handling%20and%20go%201)/

我现在已经接受了这种写法了,反过来想,C 不是也得判断返回值是否大于 0 吗

趁早放弃 go 吧

Live Templates 缓解一下

错误处理本来就是个大难题, 异常也不见得有好多多少

但是在 go 里面逢错误就 panic 的写法毫无疑问很低级

和 rust 的 Result 有得一拼

这个让我想起了地铁的手指口呼.

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

这样强迫 coder 显式处理每一个可能出现的错误,可以说是有好处的,可以说现在写输入 ife 已经成了肌肉记忆了 233333

看了下 Go 2 引入了 check & handle https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md#draft-design

<br><br>func CopyFile(src, dst string) error {<br> handle err {<br> return fmt.Errorf("copy %s %s: %v", src, dst, err)<br> }<br><br> r := check os.Open(src)<br> defer r.Close()<br><br> w := check os.Create(dst)<br> handle err {<br> w.Close()<br> os.Remove(dst) // (only if a check fails)<br> }<br><br> check io.Copy(w, r)<br> check w.Close()<br> return nil<br>}<br><br>

异常可以不处理,一直抛啊。

习惯就好。

c 的返回也是这样写的。

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

每个语言都有罗嗦烦人的地方。大部分情况只能你去适应了,不想适应就换语言吧。

虽然写的很不爽,但不能否认,这样写出来的程序是比脚本语言写出来的更健壮一些。另外 try … catch 也不见得有多好

这种比 try catch 要好,
写过 10 年 C++的 是这么认为的

完全同意,这 2 个点完全是 xxx 的存在,那个 err 我先不评价什么,毕竟是特性, 但是那个类型放后面
纯粹是为了跟别人不一样 而不一样。

用上 rust,只想说没有 nil 和 null 的世界真美好。回去看以前写的 go 代码,一堆 nil 堆的像屎山一样。。

老哥,rust 这么丑陋的语法和一堆符号是怎么克服的,我试了好多次想学,看着看着就想吐了。。

#26 不是我吐槽你,Rust 除了显式生命周期难看一点以外,其他都比 Go 好多了好吗? 而且现在有 Miri 和 NLL 的支持,很少机会能写到显式生命周期了(除非写底层)

跟异常一样,往上抛,调用方处理。
当然,如果是不能处理的错误,直接 panic 也没问题。

主要是各种符号太多了,看得我脑壳晕

用 golang,打 err 自动补全 if,还算可以接受

#29 可能我写习惯了,没发现有什么太多的符号(连 JS 的一半都没有呢)

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

也就这几个比较特殊的


<br>client.get(uri).and_then(|res| { <br> println!("Response: {}", res.status()); <br><br> res.body().for_each(|chunk| { <br> io::stdout() <br> .write_all(&amp;chunk) <br> .map_err(From::from) <br> }) <br> }); <br>
有种一口气走到底的感觉,有点喘不过气。像以前 js express 那种回调层层嵌套,全是匿名函数的错觉…

看看 gopheracdamey 写的系列文章 楼主问的问题 go github wiki 有很多好资料 仔细找找不难发现

把 book 看一遍,掌握 struct,enum,match,if let 这些东西先,觉得有意思了再继续深入

已经开始支持 async/await,后面不用 and_then 这种写法。romio 了解一下

我觉得 go 的错误处理写法没啥问题,但是通常我写 go 是基本不会写 panic 和 recover 的。。

Go 的错误处理除了啰嗦点,其实没什么大毛病,这点就是继承了 C 语言程序就是输入+输入出的设计,简单。try catch 这种也不是万能的。
错误处理 Go2 做了优化,应该会少写一些 if。

其实能和 Go 语言做比较的只有 C,拿其它语言和 Go 比都不是太恰当,比如指针这个概念,大多数现代语言都放弃了,但在 Go 中却是非常核心的东西。
还有面向对象的那一堆理论,Go 完全没有,怎么去和 Java 这种比较?

通过编辑器的 snippets 来自动完成有关错误处理的代码,工作效率会高很多

if err != nil {
log.Err("%s", err)
}

rob 想保持 go 简单和地道,现在关于 go 那些改进的方案,rob 说了,可能都不会合到 go2 里面。油管视频

<iframe src="https://www.youtube.com/embed/RIvL2ONhFBI" class="embedded_video" allowfullscreen="" type="text/html" id="ytplayer" frameborder="0"></iframe>
其实 go 这门语言多年前就死了。go2 可能就是画出来的大饼,什么时候能出来,没人知道。

我也有一个 FuckErr()

这些返回错误搞得栈信息全丢了

既然选择了 Go,那么就用 Go 的方式处理错误,Go 不是一门语法“优雅”的语言

问号操作符能缓解,等 async/await 稳定后写异步也能喘气了

但是 C 有 #define,可以弄成 CHECK_RETURN(function());

都说 if err != nil 不好,我想问,你们认为好的是怎样的?

我从 if err != nil 中学到了很多,原来这个底层调用也可能报错

我已经习惯,并可能喜欢上它了

就 Rust 而言,只有错误没有异常,可能出错的地方统一用 Result<Item,Error>代替,不想处理直接往上抛直接打?号,不想处理显示报错直接.unwrap (),不想处理直接忽略有 if let,不想处理带默认值有 unwrap_or(),想处理直接用 match 处理部分或全部情况,再或者结合 map 等函数式风格随意组合,多种方式随意选择,还有 IDE/编译器提示。
不过 go 选择了类 c 的风格,强调简单,那也没哪个好或者不好的了。

就 Result 这个设计就是吸收了多年 PL 研究成果的好东西,配合自带的各种方法,写起代码行云流水。错误能处理的就处理,不能处理就抛给 caller,还能配合编译器进行类型检查,Monad 的应用,这么好的东西有人理解不了,硬说跟 error code 一样,还能说什么。我觉得这些人用 Go 跟 C 都挺好的,记得不要忘记检查错误码就好了

你们这帮 Java 转 Go 的肯定都喜欢 try,就是习惯
你看像我们 C++转 Go 的从来不会提这类问题~

这都能讨论这么多,我的天,不就是个 Monad 随手就能解决的问题么,真是尴尬

你们这些都不看错误怎么处理的人 能写出什么严谨的程序

换个语言

pascal 也是放后面啊,还有 var

Rust 的 Result 和 Option 不知道比 go 的 err 高到哪里去了🙃。

习惯成自然

slice[0:100]
当 100 超出了 len(slice),就报错了,特别烦这个,有解决方案么

你为什么需要访问越界的元素?

吐槽 err 的几乎是喜欢把所有都错误 try catch 的人,虽然确实很啰嗦,但是这个特性写过 c/c++的人就知道,还是比较方便的.
更严谨,也更啰嗦,至少更能了解程序内部哪个地方出错了

挺好的 期待 2.0

java try catch 有堆栈信息啊,一样能看到哪行错了,把所有代码整个 try catch 完事。go 每一个调用都要写。

在Golang(Go语言)中,优雅地处理错误(err)是编写健壮、可读和可维护代码的关键。以下是一些最佳实践:

  1. 立即检查错误:在函数调用后立即检查错误,避免错误被遗漏或延迟处理。例如:

    file, err := os.Open("example.txt")
    if err != nil {
        log.Fatal(err)
    }
    
  2. 使用命名返回值:当函数有多个返回值时,特别是包含错误时,使用命名返回值可以提高代码清晰度。

    func readFile(filename string) (string, error) {
        data, err := ioutil.ReadFile(filename)
        if err != nil {
            return "", err
        }
        return string(data), nil
    }
    
  3. 自定义错误类型:为特定错误定义类型,以便进行类型断言或类型开关,提供更详细的错误处理逻辑。

    type MyError struct {
        Code    int
        Message string
    }
    
    func (e *MyError) Error() string {
        return fmt.Sprintf("Error %d: %s", e.Code, e.Message)
    }
    
  4. 日志记录:在生产环境中,使用日志记录错误详细信息,而不仅仅是打印到标准输出或标准错误。

  5. 包装错误:使用fmt.Errorferrors.Wrap(需要github.com/pkg/errors包)来包装错误,添加上下文信息。

  6. 避免panic:除非在无法恢复的严重错误情况下,否则避免使用panic

通过遵循这些实践,你可以确保你的Go代码在处理错误时既优雅又高效。

回到顶部