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

blog: remove panic and recover example from panic recover defer entry #26799

Closed
nhooyr opened this issue Aug 4, 2018 · 4 comments
Closed

blog: remove panic and recover example from panic recover defer entry #26799

nhooyr opened this issue Aug 4, 2018 · 4 comments

Comments

@nhooyr
Copy link
Contributor

nhooyr commented Aug 4, 2018

At https://blog.golang.org/defer-panic-and-recover

For a real-world example of panic and recover, see the json package from the Go standard library. It decodes JSON-encoded data with a set of recursive functions. When malformed JSON is encountered, the parser calls panic to unwind the stack to the top-level function call, which recovers from the panic and returns an appropriate error value (see the 'error' and 'unmarshal' methods of the decodeState type in decode.go).

However, this is a poor example and a misuse of panic and recover as exceptions. See https://golang.org/doc/effective_go.html#panic

The example will be invalid soon with the release of go 1.11 as well. The panic/recover was removed from the unmarshal code. See master's

func (d *decodeState) unmarshal(v interface{}) error {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return &InvalidUnmarshalError{reflect.TypeOf(v)}
}
d.scan.reset()
d.scanWhile(scanSkipSpace)
// We decode rv not rv.Elem because the Unmarshaler interface
// test must be applied at the top level of the value.
err := d.value(rv)
if err != nil {
return err
}
return d.savedError
}
versus go 1.10's
func (d *decodeState) unmarshal(v interface{}) (err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
panic(r)
}
err = r.(error)
}
}()
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return &InvalidUnmarshalError{reflect.TypeOf(v)}
}
d.scan.reset()
// We decode rv not rv.Elem because the Unmarshaler interface
// test must be applied at the top level of the value.
d.value(rv)
return d.savedError
}

Interesting and relevant article: https://about.sourcegraph.com/blog/go-when-is-it-ok-to-recover/

@nhooyr nhooyr changed the title remove panic and recover example from panic recover defer blog remove panic and recover example from panic recover defer blog entry Aug 4, 2018
@meirf
Copy link
Contributor

meirf commented Aug 4, 2018

If the decision is to replace that reference with some other "real world" example, my vote is to have the link include the commit hash. But I don't think we should reference real world code at all since referencing old code can be confusing when someone tries to find that code in master.

@dsnet
Copy link
Member

dsnet commented Aug 4, 2018

It seems that json was switched away from a panic pattern for performance reasons. That doesn't invalidate the use of panic/recover as a pattern within a single package. There are cases where performance is no concern and the panic/recover pattern really is cleaner (and easier to reason about).

I agree with @meirf to just change the URL to be a permalink to a prior version of json.

@FiloSottile FiloSottile changed the title remove panic and recover example from panic recover defer blog entry blog: remove panic and recover example from panic recover defer entry Aug 6, 2018
@FiloSottile FiloSottile added this to the Unreleased milestone Aug 6, 2018
@nhooyr
Copy link
Contributor Author

nhooyr commented Aug 7, 2018

@dsnet when would it be cleaner? It hides the fact that the internal functions can all return errors. This forced explicit error handling to make the code flow clear is one of the main reasons Go doesn't use exceptions.

@seankhliao
Copy link
Member

fixed to point to encode (which still uses panic) in #30170, https://golang.org/cl/176757

@golang golang locked and limited conversation to collaborators Jan 31, 2022
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

6 participants