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

false positive on first class function #19

Open
carnott-snap opened this issue Aug 14, 2019 · 1 comment
Open

false positive on first class function #19

carnott-snap opened this issue Aug 14, 2019 · 1 comment

Comments

@carnott-snap
Copy link

summary

Similar to #18, when the http.Response.Body.Close method is extracted and called, bodyclose misses the call and incorrectly warns:

resp, err := http.Get("http://example.com/")
if err != nil {
        // handle error
}
f := resp.Body.Close
defer f()
body, err = ioutil.ReadAll(resp.Body)

background

While this example is so simple as to be meaningless, the core problem comes up when trying to handle the potential error that io.Closer.Close can return:

func pick(one *error, two func() error) {
        err := two()
        if one != nil && *one == nil {
                *one = err
        }
}

func call() (err error) {
        resp, err := http.Get("http://example.com/")
        if err != nil {
                // handle error
        }
        defer pick(&err, resp.Body.Close)
        _, err = ioutil.ReadAll(resp.Body)
        if err != nil {
                // handle error
        }
        return nil
}

This is resolved if you inline/duplicate the pick method, defer func() {if close := resp.Body.Close(); err == nil { err = close } }(), since now there is a direct call to resp.Body.Close(), but the polymorphism and convenience of making a function for this is paramount.

It is also worth noting that defer func(f func() error) { f() }(resp.Body.Close) also fails.

@carnott-snap
Copy link
Author

It looks like passing the io.Closer into pick works around this issue:

func pick(one *error, two io.Closer) {
        if err := two.Close(); one != nil && *one == nil {
                *one = err
        }
}

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

1 participant