Yes; it seemed to me that the return statement would get evaluated even after a panic. I thought of it as a special case of a deferred context - confused.
Thank you very much; On Friday, August 26, 2016 at 12:11:03 PM UTC+4:30, Axel Wagner wrote: > > I'd think, the spec is reasonably unambiguous, if not very explicit. The > second version works, because of > > For instance, if the deferred function is a function literal and the >> surrounding function has named result parameters that are in scope within >> the literal, the deferred function may access and modify the result >> parameters before they are returned. > > > and > > The recover function allows a program to manage behavior of a panicking >> goroutine. Suppose a function G defers a function D that calls recover and >> a panic occurs in a function on the same goroutine in which G is executing. >> When the running of deferred functions reaches D, the return value of D's >> call to recover will be the value passed to the call of panic. If D returns >> normally, without starting a new panic, the panicking sequence stops. In >> that case, the state of functions called between G and the call to panic is >> discarded, and normal execution resumes. Any functions deferred by G before >> D are then run and G's execution terminates by returning to its caller. > > > i.e. after recover(), the execution continues as normally and the normal > behavior is, that you can modify named return parameters and the modified > version will then be returned. > > The first version also works as expected: recover() resumes execution as > normal and you can modify result and error as wished, but they are just > variables, not return values. Thus the function returns with the return > parameters unset (as you panic'ed before setting them with return). > > If it helps, you can imagine the return values as variables, initialized > to their zero values, which can be set in two ways: Either by having a > return or by naming them, which gives you direct access. A panic won't > modify them, but a defer'ed function might, if they are named. In your > first version, you never set them; return isn't called and they are not > named. In the second version you do set them; return isn't called, but you > name them and set them from the defer'ed function. > > Maybe the confusion is about what "after the surrounding function returns" > means? Maybe you interpret that as basically a "goto the line of the return > statement and execute it", whereas the spec means it as "executing the > function epilogue and return control to the caller"? The goto-like > interpretation doesn't make sense, in any case; there could be multiple, > pairwise contradictory return statements and it wouldn't be clear which is > executed. > > FWIW I do believe the spec could be clearer here. The behavior seems > logical and expected to me, but I do have trouble justifying this intuition > with the spec. > > On Fri, Aug 26, 2016 at 9:11 AM, dc0d <kaveh.sh...@gmail.com <javascript:> > > wrote: > >> There deferred function here has not any return value - to get discarded. >> It rather assigns a value to the *closure* *err* variable. >> >> Since a defer statement "*invokes a function whose execution is deferred >> to the moment the surrounding function returns*", so I expected the *err* >> variable should have a value just before the return statement executes. >> >> The *err* variable is just a closure. Still I'm confused why the first >> version does not behave as expected - because the actual function *is >> not invoked yet* at the position of defer statement but just it's >> parameters. "*Instead, deferred functions are invoked immediately before >> the surrounding function returns*". >> >> Why this is not behaving as expected? >> >> >> On Friday, August 26, 2016 at 3:25:11 AM UTC+4:30, Vasko Zdravevski wrote: >>> >>> I put your code snippet in the playground for easier sharing: >>> https://play.golang.org/p/ZvuNwjS7ZF >>> >>> I think the spec has the answer you're looking for regarding how named >>> result parameters are handled during a panic. >>> https://golang.org/ref/spec#Defer_statements >>> >>> Specifically the sentence: >>> >>>> If the deferred function has any return values, they are discarded when >>>> the function completes. (See also the section on handling panics >>>> <https://golang.org/ref/spec#Handling_panics>.) >>>> >>> >>> Also, >>> >>>> If the function's signature >>>> <https://golang.org/ref/spec#Function_types> declares result >>>> parameters, the function body's statement list must end in a terminating >>>> statement <https://golang.org/ref/spec#Terminating_statements>. >>>> >>> https://golang.org/ref/spec#Function_declarations >>> >>> And the panic is the 'terminating statement' >>> >>> Hope this helps, >>> Vasko. >>> >>> On Thursday, August 25, 2016 at 4:19:17 PM UTC-6, dc0d wrote: >>>> >>>> Assuming we have this test: >>>> >>>> func TestRecover(t *testing.T) { >>>> f := func() (interface{}, error) { >>>> panic(`TEST`) >>>> } >>>> r, e := Recover(f) >>>> t.Log(r, e) >>>> } >>>> >>>> And two versions of *Recover* function. >>>> >>>> Version 1: >>>> func Recover(f func() (interface{}, error)) (interface{}, error) { >>>> var result interface{} >>>> var err error >>>> >>>> defer func() { >>>> if e := recover(); e != nil { >>>> err = errors.Error(fmt.Sprintf("%v", e)) >>>> } >>>> }() >>>> >>>> result, err = f() >>>> >>>> return result, err >>>> } >>>> >>>> >>>> Version 2: >>>> func Recover(f func() (interface{}, error)) (res interface{}, err error >>>> ) { >>>> defer func() { >>>> if e := recover(); e != nil { >>>> err = errors.Error(fmt.Sprintf("%v", e)) >>>> } >>>> }() >>>> >>>> res, err = f() >>>> >>>> return res, err >>>> } >>>> >>>> >>>> *Question:* Why the output of test for Version 1 is *<nil> <nil>* (*not >>>> expected/wrong*) but for Version 2 is *<nil> TEST* (*as >>>> expected/correct*)? >>>> >>>> - Go 1.7, Ubuntu 14.04 x64 >>>> >>> -- >> 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 <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > > -- 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+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.