Home > database >  can I omit defer keyword in this case?
can I omit defer keyword in this case?

Time:07-07

go func() {
        defer wg.Done()
        for i := 0; i < n; i   {
            ch <- i
        }
    }()
go func() {
        for i := 0; i < n; i   {
            ch <- i
        }
        wg.Done()
    }()

Are these two code the same? Seems the same running them and I have seen both writings.

CodePudding user response:

Those 2 seem to be identical, there may be cases when they're not. That's because deferred functions are also executed if the function is panicking.

So for example if ch is a closed channel, sending on a closed channel will panic (see How does a non initialized channel behave?), and without defer wg.Done() will not be called. With defer, it will be. This may be very important for another goroutine calling wg.Wait() to get unblocked.

Another difference is that the deferred function and its arguments are evaluated when the defer statement is executed, in your case before the loop. If the wg variable would be modified e.g. after the first send, the one with defer would not see the new value of wg, the one without defer would see that as it's evaluated after the loop.

All in all, use defer when it makes sense, and even if you or someone else later end up modifying / extending the code, it will not be forgotten. Just think of an example where someone inserts a conditional return:

go func() {
    defer wg.Done()
    for i := 0; i < n; i   {
        ch <- i
        if i == 3 {
            return
        }
    }
}()

Using defer, this won't be a problem, wg.Wait() will still be called. Without defer, it won't be.

See related questions:

Proper way to release resources with defer in a loop?

The deferred call's arguments are evaluated immediately

  • Related