Methods of reflect pkg use mostly panic instead of return error. Why so?

225 views
Skip to first unread message

Uvelichitel

unread,
Jul 20, 2022, 3:35:38 PM7/20/22
to golang-nuts
Hi, for sure i know final Go proverb -- "Don`t panic". Also Dave.Cheney "The simple rule of thumb is panic should only be used in truely exceptional cases, which, as their name suggests are rare."
Also I know there are exist circumstances where explicit panic() call looks reasonable.
I`d like to know what are the reasons in package reflect to use panic() instead of return error.
I`m working on not much epic (have about 20000 readers) post about using panic() in stdlib.
To say
$ grep -r "panic(" $GOROOT/src | wc -l                              
 gave  3218 occurrences of explicit panic() call in stdlib. Really impressive not panicking)
But design choice in reflect package intriguing me mostly.
Would be much appreciated for hints.

Axel Wagner

unread,
Jul 20, 2022, 4:52:28 PM7/20/22
to Uvelichitel, golang-nuts
The reason reflect uses panic, is for convenience. It would be inconvenient having to check an error at every reflect call.

Personally, I strongly disagree with the advice you quote by Dave. Mainly, because it doesn't actually tell you what "truly exceptional" means.
To me, the rule of thumb is:

1. Return an error, if the source of a problem is in the interaction of the process with the outside world (and can thus be fixed by the user).
2. Panic, if the source of a problem is a bug in the program (and can thus only be fixed by the developer).

reflect APIs are passed a type, so as a rule, any problem when using them is internal to the program - types can't be passed from outside the process. It indicates that the user of reflect did not code carefully enough and that they should add extra checks to prevent that panic.

Of course, there are libraries which use reflect on behalf of *their* user and which might operate based on external input. For example, encoding/json uses reflect to look up and set field names in the JSON input. However, it's the job of those libraries to then do those checks safely and translate them into errors appropriately.

If you keep to the "panic means bug and error means external error source" rule of thumb, this also means that if you check if json.Unmarshal returns an error that error is always be fixed by the user (by providing a different JSON source). If, OTOH, json.Unmarshal would return errors when it incorrectly uses reflect, a user might get an error like "can't set unaddressable value in line marshal.go:1234", which is utterly inactionable to them.

Of course, it's a rule of thumb and there will be edge-cases. But, in general, I find it extremely helpful and in the vast majority of cases very clear.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/a8c61abf-a236-47d9-99a4-ad907412f427n%40googlegroups.com.

Robert Engels

unread,
Jul 20, 2022, 5:58:31 PM7/20/22
to Axel Wagner, Uvelichitel, golang-nuts
Which is also the distinction between checked and unchecked exceptions. Checked exceptions force the caller to deal with potential errors and are harder to ignore than error codes. 

On Jul 20, 2022, at 3:52 PM, 'Axel Wagner' via golang-nuts <golan...@googlegroups.com> wrote:



Dan Kortschak

unread,
Jul 20, 2022, 7:23:33 PM7/20/22
to golan...@googlegroups.com
On Wed, 2022-07-20 at 22:51 +0200, 'Axel Wagner' via golang-nuts wrote:
> The reason reflect uses panic, is for convenience. It would be
> inconvenient having to check an error at every reflect call.

The other reason is that a panic in reflect is as close as you can get
in runtime to a compile error, which is what the non-reflect based
equivalents would generally give you for the errors that panic in
reflect.

Dan

Reply all
Reply to author
Forward
0 new messages