Very often yes I do.
Go encourages synchronous APIs, making it up to the caller to add concurrency. This is great, in my opinion. E.g. this is a common pattern:
var wg sync.WaitGroup
ch := make(chan int, len(items))
for _, item := range items {
item := item
wg.Add(1)
go func() {
defer wg.Done()
ch <- doSomething(item)
}()
}
wg.Wait()
close(ch)
for res := range ch {
…
}
Similar patterns with defer, although yes I'd say less often in a loop. Though in order to be "exception safe" (panic safe) I often do: foo, err := openFileOrSomething()
defer foo.Close()
[… do something …]
err := foo.Close()
So that even if "do something" throws exception… err… panics… the file gets closed. And double-closing is safe. That's not a closure though, in this example. So maybe not so good.