Hmm, the first few WATs are pretty bad examples. Any developer, gopher or not, should know that, when you reassign the value of a function parameter, the variable when the function returns still has its original value. It's pass-by-reference 101. Now, sure, slices and the way append work are a bit complicated to grasp at first, especially if you never used C, but this is not a WAT.<p>A lot of WATs are more bad practice than problems in the language, IMO (like WAT 8, modifying the return value twice in deferred functions, with the order being significant: who the hell writes such a code?)<p>A few ones, though, really are problematic. For instance I've been bitten more than once by variable shadowing, especially with error values. IMO, this is the weakest point of Go.
"The order of iteration for a Go map (a hashmap) is unspecified, by design."<p>I that surprising behavior? It is not only well-documented, but is in line with most other languages that offer a hash table / map / dictionary / whatever in the base language or standard library.
I was really expecting the slice WATs to carry on to talk about what I consider a real WAT: you have to perform robust checks on your input slice's capacity and length if you use append in a function, because append makes its own choice whether the array of a slice is reused or copied.<p>Here's a basic demonstration:<p><a href="https://play.golang.org/p/8zMmPwtjcxG" rel="nofollow">https://play.golang.org/p/8zMmPwtjcxG</a><p>In particular, note how this behavior can easily be forgotten when the semantics are hidden through variadic arguments that are passed an existing slice (instead of the automatically created one when you pass in actual variadic arguments).
I would add WAT 2.5: <a href="https://play.golang.org/p/gwcHh4-QhHK" rel="nofollow">https://play.golang.org/p/gwcHh4-QhHK</a><p><pre><code> func main() {
x := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println("orig: ", x)
mutate(x)
fmt.Println("append: ", x)
mutate(x[:4])
fmt.Println("sliced: ", x)
}
</code></pre>
Appending to the end of the slice creates a new slice and therefore the caller doesn't see the mutation.<p>However appending to a slice-of-the-slice leaves capacity in mutate's copy-of-the-slice to append without allocating a new backing array. Therefore mutate happy bumps the len of its slice copy and mutates the callers slice!<p>This bit me once in real production code when reusing a []byte array to avoid allocations. The bug was obviously my fault, but this behavior can be easy to inadvertently trigger if you're trying to avoid allocations!<p><i>Edit: fixed code formatting. It's 2018 YC, please please please implement at least a subset of markdown.</i>
Nils are among the biggest wats in Go in my experience. "useful nils" just compounds "the billion dollar mistake" into something even more nefarious and even harder to identify during code review.<p>Along similar lines: WAT 15. Under what circumstances do you expect a nil var return to become non-nil? <i>Did you even know that was possible?</i>
> Go avoids magic<p>What? Go is all about magic. All the std lib stuff that is able to take any type works by magic.<p>Those "obscure rules" (which I prefer to call being able to reason about code) look like they are going to get added in Go 2.<p>It's odd how programmers think polymorphism is this obscure thing when it's available in almost every typed language.
I feel like WAT3 is the only real WAT.<p>Looking up a key in a map you didn't "make" gives you the zero value. I think that's consistent with much of Go. But if appending to a nil slice works, assigning to a key should never panic, even if you didn't "make" it first.
I feel like every language should have at least one "wat" style talk or article. Even for languages you adore, it's important to understand the quirks, shortcomings, and issues in a context that might seem absurd to an outside developer.
<i>nil is weird in Go, and in most languages with an equivalent concept. It's a "hole in the type system"</i><p>In Smalltalk, nil just contains the sole instance of the UndefinedObject class. It's not a hole in the type system. Instead, it becomes a paradox in the inheritance system, because it's used as a superclass.<p>Here's a WAT. Smalltalk is actually strongly typed. It's just that everything has the same type of Object. (The type system has no holes. However, it's the size of a thimble!)
I didn't finish reading all the WATs, but if these are the best WATs about Go, it must be a very consistent language.<p>The first two, for example, aren't WATs at all. The Go book is very clear that you need to use the result of `append` to get the modified slice. WAT 4, map traversal is unordered, is not at all a WAT. WAT 7, maps are reference types, is also not surprising at all. WAT 8 is also not a WAT, defers are defined to be processed in LIFO order, and the rest falls out of how named returns work. This was a waste of time :(
You call that a WAT? I'll show you a WAT.<p><a href="https://play.golang.org/p/ePRpDbaFaRl" rel="nofollow">https://play.golang.org/p/ePRpDbaFaRl</a>
This old blog post has a pretty good explanation about how Go slice works: <a href="https://blog.golang.org/go-slices-usage-and-internals" rel="nofollow">https://blog.golang.org/go-slices-usage-and-internals</a><p>Once you realize slices are just (pointer, length, capacity) structures, and the structure itself is copied by value, the first 2 WAT is pretty trivial.
WAT 3 and WAT 10 were surprising for me.<p>WAT 3 becomes less surprising when you consider that a method on a pointer can be called and can return a valid result even if the pointer is nil.<p>WAT 10 just seems inconsistent. I said this before, and I'll say it again: shadowing does more harm than good.<p>The rest are pretty trivial for anyone who worked with the language for over a year or read the documentation carefully.
Now combine that with the extremely confusing net.IP and net.IP.To16() and you can get a sneaky bug that I've seen in practice.<p><a href="https://play.golang.org/p/SGgR4RSCPvM" rel="nofollow">https://play.golang.org/p/SGgR4RSCPvM</a>
The video for the talk is now available: <a href="https://youtu.be/zPd0Cxzsslk" rel="nofollow">https://youtu.be/zPd0Cxzsslk</a>