Two things to note about this. 

First, if the "everything else" deferred to might include a return 
statement, then this could result in the same "silent failure" behavior.

Secondly - use this pattern with great caution. It is critical to confirm 
that a double close on ifDB is explicitly allowed. For example, if you have 
an io.Closer <https://golang.org/pkg/io/#Closer>, then, according to the 
documentation, the behavior of a double close is not specified. IMHO, if 
the package documentation does not explicitly allow double close, I would  
consider doing so to to be a bug.


Only do this if you can confirm that a double close on  ifDB

On Thursday, March 21, 2019 at 6:11:04 AM UTC-4, rog wrote:
>
> This issue is why I like having idempotent close. Do:
>
>    defer ifDB.Close()
>
> but also, after everything else is complete, do:
>
>     if err := ifDB.Close(); err != nil {
>         handle error case
>     }
>
> That way if you return early on error your connection is still closed, but 
> you can still write the obvious code for checking the close error when 
> everything else has succeeded.
>
>
> On Thu, 21 Mar 2019 at 09:41, Amnon Baron Cohen <amn...@gmail.com 
> <javascript:>> wrote:
>
>> The idiomatic Go way is to write
>>
>>    defer  ifDB.Close()
>>
>> Simple is better than clever.
>>
>> + Readability does matter.
>>
>>
>> And in situations where you really need to check that the connection was 
>> successfully closed, and
>> you have a workable scheme for recovering from this situation, then write 
>> a named helper function
>> which encompasses this logic, rather than writing a convoluted anonymous 
>> function.
>>
>> And make sure that all the execution paths in this function have unit 
>> tests.
>>
>>
>>
>> On Tuesday, 19 March 2019 23:57:51 UTC, David Collier-Brown wrote:
>>>
>>> It's a known bad thing to defer a close for anything buffered, as 
>>> discussed at https://www.joeshaw.org/dont-defer-close-on-writable-files/
>>> but some constructs lack a Sync() call.
>>>
>>> For example, I have code like
>>>         ifDB, message, err := OpenInflux(server, debug)
>>>         if err != nil {
>>>                 // If this fails, fail fast so we notice
>>>                 panic(fmt.Errorf("failed to open and ping influxDB, %s 
>>> %v",
>>>                         message, err))
>>>         }
>>>         defer func() {
>>>                 err = ifDB.Close()
>>>                 if err != nil {
>>>                         // This may be a harmless, very bad thing
>>>                         panic(fmt.Errorf("failure closing connection to 
>>> influxDB, %v", err))
>>>                 }
>>>         }()
>>>
>>>
>>> which closes an influxDB database, but will panic if the close fails.
>>>
>>> Separate logic makes sure I have passed the point at which the data is 
>>> committed before I commit my reading of input, so eventually the data will 
>>> be reread and rewritten. Nevertheless, this is exceedingly complex, and the 
>>> comment sums it up: "a harmless, very bad thing".
>>>
>>> Is there an idiomatic way to address this? I ended up reading influxDB 
>>> code and doing all sorts of deranged safety-critical-system DFAs to 
>>> reassure myself this will actually work, but every time I do that, my brain 
>>> hurts!
>>>
>>> --dave
>>>
>>>
>>> -- 
>> 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