-
Notifications
You must be signed in to change notification settings - Fork 41
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
AppendInvoke silently drops errors subtly #61
Comments
This seems to be expected given how https://go.dev/play/p/eF8TmyEnTxt func t1() int {
var i int
defer func() {
i++
}()
return i
}
func t2() (i int) {
defer func() {
i++
}()
return i
}
func main() {
fmt.Println(t1())
fmt.Println(t2())
} Results in:
Even playing with pointers does not work around this: func t3() int {
var i int
ii := &i
defer func() {
*ii++
}()
return *ii
}
// returns 0 My brief reading of the spec here https://go.dev/ref/spec#Defer_statements calls out that you need to be using named returns for defers to modify the return value:
|
This is a good point, but yeah @rabbbit is right, because of how defers work, the library can't address this.
|
As discussed in #61, if you attempt to use `defer multierr.AppendInvoke` with an error that is not a named return, the system will lose the error. ```go func fails() error { return errors.New("great sadness") } func foo() error { var err error defer multierr.AppendInvoke(&err, multierr.Invoke(fails)) return err } func main() { fmt.Println(foo()) // nil } ``` https://go.dev/play/p/qK4NR-VYLvo This isn't something the library can address because of how defers work. This change adds a warning about the error variable being a named return in all places where we suggest use of multierr with defer. While we're at it, this makes use of the new `[Foo]` godoc syntax to generate links to other functions in the package in "See Foo" statements in the documentation.
As discussed in #61, if you attempt to use `defer multierr.AppendInvoke` with an error that is not a named return, the system will lose the error. ```go func fails() error { return errors.New("great sadness") } func foo() error { var err error defer multierr.AppendInvoke(&err, multierr.Invoke(fails)) return err } func main() { fmt.Println(foo()) // nil } ``` https://go.dev/play/p/qK4NR-VYLvo This isn't something the library can address because of how defers work. This change adds a warning about the error variable being a named return in all places where we suggest use of multierr with defer. While we're at it, this makes use of the new `[Foo]` godoc syntax to generate links to other functions in the package in "See Foo" statements in the documentation.
As discussed in #61, if you attempt to use defer multierr.AppendInvoke with an error that is not a named return, the system will lose the error. func fails() error { return errors.New("great sadness") } func foo() error { var err error defer multierr.AppendInvoke(&err, multierr.Invoke(fails)) return err } func main() { fmt.Println(foo()) // nil } https://go.dev/play/p/qK4NR-VYLvo This isn't something the library can address because of how defers work. This change adds a warning about the error variable being a named return in all places where we suggest use of multierr with defer. While we're at it, this makes use of the new [Foo] godoc syntax to generate links to other functions in the package in "See Foo" statements in the documentation.
Closing because documentation was updated in #63, and there's nothing we can do at the library level besides that. |
Thanks for putting together this library!
The behavior I found surprising was that if you do not use the less-common pattern where you define variables in the function return signature, that using
defer multierr.AppendInvoke(&err, someInvoker)
will not have the error returned bysomeInvoker
included in the error that is returned by the function.Example: https://go.dev/play/p/JoSVtFwapQL
Note how
outer20
is missingfoo
from its list of errors.I guess Go's runtime is returning (or copying the return value) before the defer is running when the return value is defined in the function body vs in the function signature.
The text was updated successfully, but these errors were encountered: