In Go, one often sees the following idiom:
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
defer src.Close()
dst, err := os.Create(dstName)
if err != nil {
return
}
defer dst.Close()
return io.Copy(dst, src)
}
Is there any reason why the defer
statement comes after the error check? My guess is that this is done in order to avoid dereferencing nil
values in case err
was not nil
.
If the file Open
or Create
fails then you don't have a valid *File
to close. The problem wouldn't be a nil
value for *File
as Close
() will check for nil
and simply return immediately in that case - the problem might be if the *File
value is non-nil but invalid. Since documentation for os.Open()
doesn't explicitly state that a failed call to Open()
returns a nil value for *File
you can't rely that all underlying implementations of it do in fact return a nil value or will always return a nil value..