Go 转到延迟-在循环中打开和复制文件
如果我在Go 转到延迟-在循环中打开和复制文件,go,Go,如果我在for循环中打开一个文件,并将在迭代结束时完成,我应该立即调用Close,还是使用闭包调用trickDefer 我从chan字符串中读取了一系列文件名,其中包含要复制到zipfile中的数据。这些都是在go func中处理的 go func(fnames <-chan string, zipfilename string) { f, _ := os.Create(zipfilename) // ignore error handling for this example
for
循环中打开一个文件,并将在迭代结束时完成,我应该立即调用Close
,还是使用闭包调用trickDefer
我从chan字符串
中读取了一系列文件名,其中包含要复制到zipfile中的数据。这些都是在go func中处理的
go func(fnames <-chan string, zipfilename string) {
f, _ := os.Create(zipfilename) // ignore error handling for this example
defer f.Close()
zf := zip.NewWriter(f)
defer zf.Close()
for fname := range fnames {
r, _ := os.Open(fname)
w, _ := zf.Create(r.Name())
io.Copy(w, r)
w.Close()
r.Close()
}(files, "some name.zip")
还是继续编写代码?您应该检查错误。我知道这只是一个例子,但在这种情况下,这很重要。如果您所做的只是defer Close(),则实际上无法检查defer期间是否有错误 我写这篇文章的方法是创建一个helper函数:
func copyFileToZip(zf *zip.Writer, filename string) error {
r, err := os.Open(filename)
if err != nil {
return err
}
defer r.Close()
w, err := zf.Create(r.Name())
if err != nil {
return err
}
defer w.Close()
_, err = io.Copy(w, r)
if err != nil {
return err
}
return w.Close()
}
一旦添加了所有错误处理,函数就足够大,可以使其成为命名函数。它还有另外一个好处,即在关闭编写器时检查错误。没有必要检查读卡器的错误,因为这不会影响数据是否写入。您应该检查错误。我知道这只是一个例子,但在这种情况下,这很重要。如果您所做的只是defer Close(),则实际上无法检查defer期间是否有错误 我写这篇文章的方法是创建一个helper函数:
func copyFileToZip(zf *zip.Writer, filename string) error {
r, err := os.Open(filename)
if err != nil {
return err
}
defer r.Close()
w, err := zf.Create(r.Name())
if err != nil {
return err
}
defer w.Close()
_, err = io.Copy(w, r)
if err != nil {
return err
}
return w.Close()
}
一旦添加了所有错误处理,函数就足够大,可以使其成为命名函数。它还有另外一个好处,即在关闭编写器时检查错误。检查读卡器的错误是不必要的,因为这不会影响数据是否被写入。我不认为其中一个比另一个更地道,但第一个更简单。检查错误值是惯用的方法。当您添加代码时,第二种方法会更简单。我不认为一种方法比另一种方法更地道,但第一种方法更简单。检查错误值是惯用的方法。当您添加该代码时,第二种方法会更简单。
延迟w.Close()
和返回w.Close()
都可以吗?这取决于类型。对于大多数类型,可以多次调用Close。我碰巧知道(通过阅读源代码)调用Close两次是有效的zip.Writer。第二次返回错误,但这是在延迟期间,因此不重要。是否可以同时执行延迟w.Close()
和返回w.Close()
?这取决于类型。对于大多数类型,可以多次调用Close。我碰巧知道(通过阅读源代码)调用Close两次是有效的zip.Writer。第二次返回错误,但这是在延迟期间,因此不重要。