Go 在重写变量上延迟文件关闭
我正在学习Go,所以我尝试编写一个应用程序,从JSON API获取一些数据并将其放入文件中。我编写了一个函数来检查我的文件是否存在,如果不存在,就创建它Go 在重写变量上延迟文件关闭,go,Go,我正在学习Go,所以我尝试编写一个应用程序,从JSON API获取一些数据并将其放入文件中。我编写了一个函数来检查我的文件是否存在,如果不存在,就创建它 func encureRefileExists(文件路径字符串){ f、 错误:=os.Open(存储文件) 延迟函数(){ 错误:=f.Close() 如果错误!=零{ fmt.Printf(“无法关闭文件%q,错误:%q”,文件路径,错误) 返回 } fmt.Printf(“文件%q已关闭”,文件路径) }() 如果错误!=零{ 如果os.
func encureRefileExists(文件路径字符串){
f、 错误:=os.Open(存储文件)
延迟函数(){
错误:=f.Close()
如果错误!=零{
fmt.Printf(“无法关闭文件%q,错误:%q”,文件路径,错误)
返回
}
fmt.Printf(“文件%q已关闭”,文件路径)
}()
如果错误!=零{
如果os.IsNotExist(错误){
f、 err=os.Create(存储文件)
如果错误!=零{
恐慌(错误)
}
返回
}
恐慌(错误)
}
}
我的考虑是:
打开
,创建
,…),则调用延迟f.Close()
是一件坏事,是否应该仅在错误检查后调用它os.Open
调用中总结该文件不需要关闭,因为返回了错误,不需要将os.Create
的结果分配给新变量并单独关闭,对吗f.Close()
失败时该怎么办,除了放置一些日志或忽略它之外,还有什么要做的吗我想说你的方法有很多“错误” 首先,如果一个函数被定义为返回一个错误和其他值,那么您几乎应该首先检查错误,只有在没有错误的情况下才尝试使用其他值。
一个众所周知(但罕见)的例外是
io.Reader
和io.Writer
接口的方法,该接口可能会返回非零的读/写字节数和非nil
错误
虽然延迟调用不会立即使用分配给f
的值,但如果调用os.Open
失败,因此返回非nil
错误,则分配给f
的值实际上未定义。Go不是C,要让它在真正未初始化的内存上运行,必须进行大量操作(并使用不安全的),但最重要的事实是,大多数具有多个返回值的函数,其中一个是error
,不要记录任何状态如果错误
不是nil
,其余的值将是
特别是,os.File
可以自由返回任何值作为第一个返回值,而第二个返回值是非nil
错误
嗯,细心的程序员通常不会做愚蠢的事情,os.Open
实际上返回nil
作为第一个返回值,而第二个error
不是nil
但是,想想如果对os.Open
的调用失败会发生什么:变量f
被赋值为nil
,然后对该变量上关闭的函数literal的延迟调用将尝试调用Open
的nil
值
同样,在指针接收器上定义的一些方法知道当它们的接收器是nil
时该做什么,但是Open
不是它们中的一个,它只会在尝试取消引用nil
指针时爆炸
是的,您似乎通过后续调用os.Create
来“补偿”这一点,这是不允许通过使用panic
失败的,但这只会创建复杂的代码。我认为您提出这个解决方案是为了不编写两个defer
块,一个用于成功的os.Open
,另一个用于成功的os.Create
,但如果我是您,我只编写了一个简单的“Open或Create”将返回与os.Open
或os.Create
do相同值的帮助程序。信不信由你,Go已经有一本书了;-)
因此,大多数情况下正确的使用模式是
f,err:=os.Open(…)
如果出错!=零{
//处理错误
返回。。。
}
//此时,已知f处于良好状态
延迟函数(){
错误:=f.Close()
// ...
}()
其次,不需要采用先尝试打开,然后在不存在的情况下创建的方法:os.open
和os.create
可以被看作是通用接口的简化接口(它非常接近于。
使用O_CREATE
标志,如果文件不存在,该函数将自动创建该文件,并且作为一个额外的功能,该功能会自动创建与检查相关的文件(虽然您的方法与文件系统有着天然的竞争:在尝试打开文件和尝试创建文件之间,其他一些进程可能会创建文件,从而导致第二次调用失败)
关于你的最后一个问题,答案是“视情况而定”:
- 如果打开一个文件进行读取,并且您已成功读取该文件中的所有(必需)数据,则关闭该文件时出现错误并不意味着您丢失了任何内容,实际上不太可能发生。在大多数情况下,将其记录为警告并继续是可以的
- 如果某个文件是为写入而打开的,未能关闭它可能意味着在调用
Close
之前,您可能丢失了写入该文件的部分内容。
调用Close
失败的一个常见示例是驻留在网络文件系统(如NFS或CIFS)上的文件。
具体应该采用什么策略在很大程度上取决于执行该操作的流程的性质:例如,如果您正在编写电子邮件服务器,则无法存储消息应导致放弃并正确地将问题传达给发送客户端;如果您正在编写交互式应用程序,则可能会询问用户至少,允许他们重试或更改文件的位置,然后重试或其他操作
见否。是。视情况而定。