3 ms·
Crikey! You wouldn't wanna allocate closures in a loop anyway, would you? Even if the compiler is smart about it. Doesn't read so well either.. what's wrong wit
by dualogy 9y ago
Crikey! You wouldn't wanna allocate closures in a loop anyway, would you? Even if the compiler is smart about it. Doesn't read so well either.. what's wrong with adding a simple argument to your anonymous-func allocated outside of a loop? It's readable, and there are no 'gotchas'. The args are evaluated at the point of defer/go, not func execution. Simples.
Shadowing bites you sooner or later if it becomes a habit and gains you almost nothing in real terms. I keep running into subtle nasties in coworkers' commits from quick'n'dirty-that-stayed "convenience" shadowings. Need I say `err`.. of course linters help, but aren't a given in a "bring-your-own chosen dev-env" team. =)
- knorker 9y ago> Crikey! You wouldn't wanna allocate closures in a loop anyway, would you? 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.
- dualogy 9y agoNone of your explanations/examples counter the fact that you could also declare your anonymous-func just above your loop in a local, ie. `doit:= func(item...` and then simply `go doit(item)` in the loop. You get: a leaner terser loop to later have to read through, no iteration-scope "gotcha", no need to elaborately spell out explicit shadowings for what are naturally semantically really func "args" already/anyway, at worst identical cost (or better).. But well, guess it comes down to subjective stylistic preferences here =) > So that even if "do something" throws exception… err… panics… the file gets closed. Your defer as placed in your above example is already scheduled to run always, even on a later panic. (After all, how else could one `recover` from a `panic` if it wasn't for `defer`?) I don't see the point of the double-closing at all here..
- knorker 9y agoYeah, I could declare it above. But it's subjectively harder to read, having to jump around. Like you say: subjective. > Your defer as placed in your above example is already scheduled to run always Yes, brainfart. Sorry. This is from a completely separate recommendation to defer a close (dropping error return), but also manually close so that closing errors can be surfaced. Matters for e.g. writing files (not so much reading), especially when you don't flush manually.