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

G307: Why is defer os.File.Close bad? #453

Closed
imirkin opened this issue Mar 30, 2020 · 3 comments
Closed

G307: Why is defer os.File.Close bad? #453

imirkin opened this issue Mar 30, 2020 · 3 comments

Comments

@imirkin
Copy link

imirkin commented Mar 30, 2020

It seems like this was recently added, but without any justification. If a file close fails, there's no real recourse to that... what is one supposed to do with it?

I would actually imagine that defer foo() where foo returns an error is the bad case, except os.File.Close, which is clearly OK...

@ccojocar
Copy link
Member

Please see for more details this article https://www.joeshaw.org/dont-defer-close-on-writable-files/ and also the 3rd point on this https://blog.learngoprogramming.com/5-gotchas-of-defer-in-go-golang-part-iii-36a1ab3d6ef1.

@ccojocar
Copy link
Member

Thanks for reporting this. I am going to close it for now.

@sjl
Copy link

sjl commented May 22, 2020

The first update in the first blog post mentions that a common solution to this problem is to defer one Close() operation on the file to ensure it gets closed no matter what, as long as you also check an explicit Close() call later:

func doSomething() error {
    f, err := os.Create("foo")
    if err != nil {
        return err
    }
    defer f.Close()

    if _, err := f.Write([]byte("bar"); err != nil {
        return err
    }

    if err := f.Close(); err != nil {
        return err
    }
    return nil
}

The blog post seems mostly okay with this, except that os.File.Close() wasn't explicitly documented to be safe to call Close() on multiple times. Since then, the documentation has been updated. So now it seems that this pattern is a reasonable way to work.

gosec still flags it as a problem, and we have to // #nosec the defer calls all the time, which is annoying. I don't know if it's possible to detect whether .Close() is called later in the function to avoid these false positives, but if it's possible, that would be nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants