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.

Reply via email to