I think only #1 really counts as a gotchya. #3 is literally just "spend at least 2 seconds knowing what a slice is" (which you should do! there's only like 4 data structures in Go built in, so get to know 'em all). #2 is similar.<p>My favorite gotchya is that assigning a nil pointer to an interface will not give you a nil interface.<p>Once you know what's going on, it totally makes sense, but usually you don't start out with that deep an understanding of how interfaces work, and it violates natural-looking assumptions about algebraic equality, which makes for very easy counter-intuitive behavior.<p>Example:<p><pre><code> package main
import "fmt"
func main() {
var x *ErrorX = nil
var err error = x
if err == nil {
fmt.Println("nope, this won't happen ")
} else {
fmt.Println("here's my non-nil error:", x)
}
}
type ErrorX struct{}
func (x *ErrorX) Error() string {
return "hi i'm ErrorX"
}
</code></pre>
<a href="https://play.golang.org/p/BB1b2_HDb6I" rel="nofollow">https://play.golang.org/p/BB1b2_HDb6I</a>
How do Go programmers deal with the fact that it is hard to reason about whether slices alias?<p>Go lacks const, so there's no way to prevent your caller from modifying the slice you return, or the callee from modifying the slice you pass it. Also the result of append() may or may not alias its parameter, depending on the allocator's mood that day.<p>Do Go APIs just defensively copy, or pepper APIs with "do not modify" warnings, or rely on runtime tests? Given the fact that append() may mask aliasing bugs, is there a way to make append() alias maximally?
On #3 “slicing”, on a related note for Python, remember after a new list is created from slicing, each element/item in the new list is the exact reference to the corresponding element/item in the original list. This is espeically problematic when you try to do things on a mutuable object in either list, but expect the other list remains completely shield from change. You have to do deepcopy (but for immutable object deepcopy has no effect).<p>Makes sense and probably is a given for most programming languages.
My newest two gotchas:<p>1. Don't use private attributes for struct types if you ever want to serialize/encode them (exception: Mutex and Channel Attributes). Just had to refactor a whole lot of code just, because I decided I wanted to save the struct to disc. Btw. the type itself can and probably should be private.<p>2. Don't use Pointers in map key structs. As nesting maps is a pain the simple solution is to use structs as keys. But if you do so please remember not to use any pointer fields within those structs. Again when you encode and decode maps with pointers within the key structs those pointers will bite you.
I liked how this was written. The way this was written sort of reminds me of go. It's as simple as approriate, and written in a way to be memorable. Nice UX trick deadbeef!
For #2, the "if len(a) == 0" clause is totally non-sense.<p>I hope Go supports "append(nil, data[:2]...)", which will make code much cleaner.
The last gotcha sort of leads to a different gotcha. That copy statement will only work as expected if the destination slice is large enough - thus always initialise it with the length of the (sub)slice you want to copy over. You won't get any errors if it's smaller, but you will surely not get what you desired.
There was a good post about many gotchas that was on HN a little while ago. Just to share :<p><a href="http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/" rel="nofollow">http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in...</a>
it also takes some figuring that the first character of anything needs to be uppercase if 1) you try to a function outside of the main source file, and 2) use an element from a struct in a template, i.e. {{.element}} does not work...
The first one could be mitigated by providing an array of article pointers ([]*Article). That way, article.legs = 99 would work.<p>Else, the way mentioned in the article, or (&article).legs =
99 (ugly) would work. Take your pick.
Looks like a newbie article. The gotcha that got had me a few times is closure within a loop:<p>for _, ele := range eles {
go func() { // use ele }
}<p>Since ele is a loop variable it is not captured as you might think it is. You need to copy it before the closure.
Yeah the range thing got me too.<p>At some point I tend to just ignore the second part of the range and only use the index...<p>and then after that I just switch back to a damn for loop like god intended.
I look at stuff like this and wonder why I'm reading it because I'll never use this language.. but i'm glad it's here for people who do!