跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 大家写 golang 的时候是否处理 f.Close 返回的错误值?
未分類
24 6 月 2020

大家写 golang 的时候是否处理 f.Close 返回的错误值?

大家写 golang 的时候是否处理 f.Close 返回的错误值?

資深大佬 : SimbaPeng 5

golang 里打开某个资源,通常都会在下面紧接着 defer f.Close, 这个 f 是指任何需要 close 的资源,没有特指文件。

但是 close 方法都会返回一个 err,大家在实际编码中会去处理这个 err 吗,如果处理,怎么处理呢?

记录日志之后 os.Exit() or panic ?

这 2 个我感觉都不好用啊,os.Exit()会跳过 defer 直接终止程序,也就是说如果程序中还有其他资源在 defer 里清理,都会失效。

而 panic 只会执行当前 goroutine 的 defer, 然后程序崩溃退出,如果程序在多个 goroutine 中都有 defer 要执行,那么其他 goroutine 的 defer 都不能保证执行了。难道我要在每个 goroutine 都捕获 panic 来保证程序不崩溃吗??

golang 里就没有 finally 这种只要进了 try 块就总会执行的机制吗??

大佬有話說 (17)

  • 資深大佬 : xmge

    感觉问题有点乱,整理一下:

    1. defer f.Close 的 error 处理吗?如何处理?
    2.是不是每个 goroutine 中都要写 defer {err := recover } 来捕捉异常?

  • 資深大佬 : reus

    一般不处理,如果非要处理的话,这样写

    https://gist.github.com/reusee/25836c8a6faac925fe52c1c73d122a04

  • 資深大佬 : lewinlan

    打开的资源类型不同,err 的影响肯定也不同。自己看源码注释决定。

  • 資深大佬 : Aoang

    这段时间用了一个三方库,库里面到处都是 panic 那种,它就是属于什么 error 都会处理的。

    我用这个库的时候,没有任何感受…(

    不写 recover 的话,一跑就 panic,没有一个完善的错误处理机制,不给调用者处理的机会。

  • 資深大佬 : sagaxu

    把一个 exception 搞成这样也是大道至简么

  • 資深大佬 : virusdefender

    一般 close 失败了也没啥补救的办法,打印日志意义也不大,我选择直接 defer 忽略

  • 資深大佬 : input2output

    https://www.joeshaw.org/dont-defer-close-on-writable-files/

  • 資深大佬 : fengjianxinghun

    大道至简还怕这种问题?

  • 資深大佬 : Mohanson

    close 是一个系统调用, 它出错的情况只有:

    “`
    ERRORS
    The close() system call will fail if:
    [EBADF] fildes is not a valid, active file descriptor.
    [EINTR] Its execution was interrupted by a signal.
    [EIO] A previously-uncommitted write(2) encountered an input/output
    error.
    “`

    程序中经常遇到的是 EIO, 也就是在在 close 之前, read/write 已经报错了(比如文件 fd 已经提前关闭, 网络的话 TCP 连接已经断开等), 这种情况忽略 close 的 err 才是正确的逻辑. **因为调用 close 的核心目的是释放资源, 而不管在这次调用之前资源是否已经被释放了, 程序只保证在该次调用 close 后资源一定是已经释放的状态即可.**

  • 資深大佬 : reus

    扯“大道至简”的傻逼,能不能不懂就闭嘴?

  • 資深大佬 : xmge

    “`
    f, err := os.Create(fn)
    if err != nil {
    return err
    }
    defer f.Close()
    “`

    在官方库中也是这么写的,应该如上所言,这个 error 不用管

  • 資深大佬 : lcode

    可以不处理,一般的 lint 工具也会有 ignore defer 类似的选项
    如果非要处理,可以
    1. 将错误返回,但是注意这里如果返回的话可能会覆盖代码之前的逻辑中的错误,所以最好组合到一起返回
    2. 返回错误时打印日志,或直接将定义一个 log.CallFailed(func ())类似的函数,后期运维的时候可以看到哪里 close 时出错了
    3. 排除掉应该返回错误的情况后,直接 panic

  • 資深大佬 : hellodudu86

    1.err 要处理的话最好就是返回给上层调用,有多层上报的话可以视情况 wrap 进去当前调用层的信息,上层判断的时候使用 errors.is()来处理,这样底层的代码都比较简洁且不会陷入面对错误编程的困境,可以参考下这篇文章 https://blog.golang.org/go1.13-errors

  • 資深大佬 : hellodudu86

    2.开新的 goroutine 一般都会在 defer 里面 recover 来保证不崩溃

  • 資深大佬 : CRVV

    Java 的 finally 也不保证能执行到
    https://stackoverflow.com/questions/1410951/how-does-javas-system-exit-work-with-try-catch-finally-blocks

    但是 Python 在这个情况下会执行 finally

    defer 和其它语言里的 finally 基本上是等价的,直接用就是了

    我觉得 panic 和 os.Exit 在正常运行的程序里不多见,出现了就需要改 bug 了,这个问题也没多大影响

  • 資深大佬 : ujued

    有不得不处理的时候,用匿名函数:
    defer func(){
    err := f.Close()
    // Handle or Throw
    }()

  • 資深大佬 : dawniii

    @input2output 这篇文章的观点好像是不对的。说是 close 的时候,可能有 buffer 没有落盘?可是 go 的 write 操作没有应用层 buffer 的,直接就是 write 系统调用写到 page cache 了,这时候就算进程挂了,内核也应该会自动落盘。

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具