I've been doing quite a bit of Go programming for a while now, and I've internalized all these behaviors, but this one gets me every time:<p><pre><code> var err error
if true {
foo, err := someFunction()
// err gets shadowed
}
</code></pre>
It's particularly annoying because if both foo and err are defined in the outer scope, you get a compiler error that no new variables are on the left, so you tend to forget that removing one shadows the other.
Languages probably shouldn't allow shadowing, certainly not within a single module. Think of the maintenance programmers.<p>"Defer" was probably a bad idea. It's a run-time construct - you're adding to a to-do list run at the end of the function. It's not scope oriented. Something like Python's "with" clause would have been both simpler and more useful. "with" calls "_enter" on an object when you enter a scope, and "_exit" when you leave, no matter how you leave. All the file-like and lock-like objects support "with". Python's "with" even supports exceptions properly - if you're handling an exception when "_exit" is called, the "_exit" function gets told about the exception, so it can clean up and then re-raise the exception. If an "_exit" itself needs to raise an exception, that works, too.<p>"Defer" is blind. With "defer", nobody ever finds out that the close failed to write the end of the file.
> Everyone expects these values to be scoped inside the loop, but go reuses the same memory location for every iteration.<p>I don't see this as surprising as a C++ user. Who is 'everyone' here?
It should be stated that entire teams build large systems with Go on a daily basis and don't step on these.<p>The community of professional Go programmers has arrived at practices that avoid such issues.<p>However, I wonder how many new programmers fall off early because of these corner cases.
Maybe it's just me, but in these cases when I encounter some weird behavior in a language I assume that I don't know enough of the language. It's actually not the designers fault that they are there, but my knowledge that requires more info.
For me channels and append() are the biggest language level landmines. Not so big are nils, :=, lack of panic when you go beyond last element of the slice, i.e. ([]int{0,1})[2:].<p>Libraries are a lot worse though, they are minefields.
As a Swift programmer Go programming seems riddled with a need to be perfect. I'd rather the language help me not make errors rather than assume I am perfectly aware of all the gotchas. Swift isn't perfect but it does make things less likely to confound you later.
I don't know if I'd call this a land mine, but I wish it didn't work because it confuses beginners.<p>You can type<p>for i:= range myvalues<p>In this case i is the index of the value. I'd rather they didn't allow this and instead you would just type<p>for i,_ := range myvalues
Seems that the explicit lambda capture in C++ is a good way to avoid the first issue. Implicit capture of closure variables is kinda scary when you think about it.
If only one could go back in time and fix the weird overloading of nil for pointers and interfaces...it is the one breaking change to the Go1 language guarantee that seems worth it.