Golang Go语言中大家写代码时是否处理f.Close返回的错误值?
Golang Go语言中大家写代码时是否处理f.Close返回的错误值?
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 块就总会执行的机制吗??
更多关于Golang Go语言中大家写代码时是否处理f.Close返回的错误值?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
感觉问题有点乱,整理一下:
1. defer f.Close 的 error 处理吗?如何处理?
2.是不是每个 goroutine 中都要写 defer {err := recover } 来捕捉异常?
更多关于Golang Go语言中大家写代码时是否处理f.Close返回的错误值?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
一般不处理,如果非要处理的话,这样写
https://gist.github.com/reusee/25836c8a6faac925fe52c1c73d122a04
打开的资源类型不同,err 的影响肯定也不同。自己看源码注释决定。
这段时间用了一个三方库,库里面到处都是 panic 那种,它就是属于什么 error 都会处理的。
我用这个库的时候,没有任何感受…(
不写 recover 的话,一跑就 panic,没有一个完善的错误处理机制,不给调用者处理的机会。
把一个 exception 搞成这样也是大道至简么
一般 close 失败了也没啥补救的办法,打印日志意义也不大,我选择直接 defer 忽略
大道至简还怕这种问题?
close 是一个系统调用, 它出错的情况只有: <br>ERRORS<br> The close() system call will fail if:<br> [EBADF] fildes is not a valid, active file descriptor.<br> [EINTR] Its execution was interrupted by a signal.<br> [EIO] A previously-uncommitted write(2) encountered an input/output<br> error.<br>
程序中经常遇到的是 EIO, 也就是在在 close 之前, read/write 已经报错了(比如文件 fd 已经提前关闭, 网络的话 TCP 连接已经断开等), 这种情况忽略 close 的 err 才是正确的逻辑. 因为调用 close 的核心目的是释放资源, 而不管在这次调用之前资源是否已经被释放了, 程序只保证在该次调用 close 后资源一定是已经释放的状态即可.
扯“大道至简”的傻逼,能不能不懂就闭嘴?
<br> f, err := os.Create(fn)<br> if err != nil {<br> return err<br> }<br> defer f.Close()<br>
在官方库中也是这么写的,应该如楼上所言,这个 error 不用管
可以不处理,一般的 lint 工具也会有 ignore defer 类似的选项
如果非要处理,可以
1. 将错误返回,但是注意这里如果返回的话可能会覆盖代码之前的逻辑中的错误,所以最好组合到一起返回
2. 返回错误时打印日志,或直接将定义一个 log.CallFailed(func ())类似的函数,后期运维的时候可以看到哪里 close 时出错了
3. 排除掉应该返回错误的情况后,直接 panic
1.err 要处理的话最好就是返回给上层调用,有多层上报的话可以视情况 wrap 进去当前调用层的信息,上层判断的时候使用 errors.is()来处理,这样底层的代码都比较简洁且不会陷入面对错误编程的困境,可以参考下这篇文章 https://blog.golang.org/go1.13-errors
2.开新的 goroutine 一般都会在 defer 里面 recover 来保证不崩溃
有不得不处理的时候,用匿名函数:
defer func(){
err := f.Close()
// Handle or Throw
}()
这篇文章的观点好像是不对的。说是 close 的时候,可能有 buffer 没有落盘?可是 go 的 write 操作没有应用层 buffer 的,直接就是 write 系统调用写到 page cache 了,这时候就算进程挂了,内核也应该会自动落盘。
在Golang(Go语言)编程中,处理文件操作时,正确管理资源释放和错误处理是至关重要的。对于f.Close()
这一操作,尽管在某些简单脚本或示例代码中可能会忽略其错误返回值,但在生产级代码中,推荐始终检查f.Close()
返回的错误值。
f.Close()
用于关闭一个打开的文件,并释放与之相关的资源。如果Close
方法调用失败(例如,由于底层文件系统的问题),它会返回一个非nil
的错误值。不处理这个错误可能导致资源泄露或未定义行为,特别是在长时间运行的服务器或应用程序中。
一个标准的做法是使用if err := f.Close(); err != nil { /* 处理错误 */ }
的模式来确保任何关闭文件时发生的错误都能被捕获并适当处理。这可能包括记录错误日志、尝试其他恢复措施或至少确保程序不会因未处理的错误而静默失败。
在某些情况下,如果上下文允许(比如程序的其余部分能够容忍文件未成功关闭的情况),可以选择仅记录错误而不中断程序执行。然而,这种决策应基于充分的风险评估和对应用程序健壮性的深刻理解。
总之,虽然Go语言提供了简洁的错误处理机制,但开发者在编写涉及资源管理的代码时,仍需保持谨慎,确保所有可能的错误路径都得到妥善处理。