To me this works as expected.

In both your versions, the return statement in Recover() is not even 
reached since the call to f panics. You recover from the panic in your 
defer statement and assign the err variable your error value.

Since in your first version, that variable is not returned, you do not see 
it outside of your Recover() function.
In your second version, the err variable is declared in your function 
signature, so it does get returned, hence why you see it.

Le vendredi 26 août 2016 09:11:19 UTC+2, dc0d a écrit :
>
> 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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to