之前一直用 VSCode
写 golang
代码,昨天切换到了 Goland IDE
后打之前写的代码,冒出了一堆语法的 warning 警告
其中最多的就是如下 f.Close()
方法未进行错误处理的警告
之前在 VSCode 中都这样写习惯了,从来没有发现任何的问题,难道通过 defer
执行的 Close 方法也需要进行错误处理?
抱着事出必有因的态度,查找相关资料,发现 Close() 方法确实有一个 error 的返回值,但在通常的写法中,都是直接当成无返回方法直接调用了,
甚至直接在 github 上搜索代码,大部分也都是直接 defer f.close()
的写法。
那么原则上到底是应该忽略错误返回值?还是应该手动处理返回值呢?
这应该从使用场景上来分别看待 Close()
通常是在对 IO 的读写操作完成后,用于结束会话或关闭打开的文件对象的操作
例如: 关闭已经处理完成的数据库连接 *db.Close()
, 关闭一个已经读写完成的文件对象 *File.Close()
等等;
如果在程序逻辑中,对于打开的 IO 对象,仅仅只是做了读取操作,那么在关闭这个 IO 对象时,可以安全的忽略 Close() 方法的返回值;
// 常用写法,忽略错误返回值,但 Goland 会有提示
defer f.Close()
// 使用匿名函数,明确定义忽略错误返回,不会有语法提示
defer func(){
_ = f.Close()
}()
如果在程序逻辑中,对于打开的 IO 对象,有写入或更改的操作,则在关闭对象时,应该要明确处理错误返回
因为在某些 IO 场景下,是在执行 Close()
操作时才会真正处理和写入数据到存储器,通过关闭对象时的错误返回,能明确了解数据存储是是否存在异常,例如数据是否成功持久化写入磁盘了,所以应该明确显式的处理关闭异常;
//显示返回关闭时的错误细节
defer func(){
if err := f.Close(); err !=nil {
log.Printf("%v", err)
}
}()
总结
1. 对于只读处理 IO 对象,在 Close()
关闭时可以安全的忽略异常返回
2. 对于有写入或变更操作的 IO 对象,在 Close()
关闭时应该要显式地捕获或处理异常返回