Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/blog: Error in defer-panic-and-recover article #34690

Closed
Xerock opened this issue Oct 4, 2019 · 1 comment
Closed

x/blog: Error in defer-panic-and-recover article #34690

Xerock opened this issue Oct 4, 2019 · 1 comment

Comments

@Xerock
Copy link

Xerock commented Oct 4, 2019

What did you expect to see?

func CopyFile(dstName, srcName string) (written int64, err error) {
    src, err := os.Open(srcName)
    defer src.Close()
    if err != nil {
        return
    }

    dst, err := os.Create(dstName)
    defer dst.Close()
    if err != nil {
        return
    }

    return io.Copy(dst, src)
}

What did you see instead?

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)
}

With the current code example, in the case of a non-nil error, the defer isn't stacked before the return occurs, so the function will return without closing the source file.

Little program to prove my point : https://play.golang.org/p/UAdMVffys_P

@gopherbot gopherbot added this to the Unreleased milestone Oct 4, 2019
@bcmills
Copy link
Contributor

bcmills commented Oct 4, 2019

This aspect of the example is correct and idiomatic as written.

Like most Go functions, os.Open and os.Create return zero-values (in this case, nil pointers) for the other arguments when they return a non-nil error, and calling Close on a nil receiver is generally nonsensical.

In this case, the nonsensical call is masked by the permissiveness of (*os.File).Close. Rather than panicking (as many Close implementations would for nil receivers), it returns ErrInvalid:

go/src/os/file_unix.go

Lines 230 to 232 in fc70527

if f == nil {
return ErrInvalid
}

@bcmills bcmills closed this as completed Oct 4, 2019
@golang golang locked and limited conversation to collaborators Oct 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants