So you mentioned that Go has locking primitives in addition to channels (buffered and unbuffered), because sometimes locking is more convenient. You didn't have
to add locks, because locks can be simulated using channels, and vice versa, but sometimes it's more convenient or efficient to have the right interface readily available.
This isn't all that different from Haskell, where we have two primitive mechanisms - 1-place buffered channels (MVar), and transactional memory (STM). On top of these are built a wide variety of abstractions, but you could do the same in Go. For example, Haskell's unbounded asynchronous channels are built out of 1-place buffered channels (MVar), and I'm sure you could do exactly the same thing in Go. So I don't think the design is fundamentally different: Go has multiple synchronisation mechanisms; the choice of primitives is different from Haskell, but overlapping.
Perhaps the difference is more cultural. In Haskell people often build their own abstraction layers, because there's little incentive not to. Haskell is really good at abstraction, so these layers can be indistinguishable from another concurrency model - see for example the monad-par library, which is really just a library using the basic concurrency primitives underneath. At Google there seems to be a strong emphasis on writing code that others can quickly understand, which I imagine would discourage the use of abstractions that aren't widely accepted. That's my guess anyway. I'm not suggesting it's bad: certainly I have a hard time reading a lot of random Haskell code that I come across, because Haskell programmers often tend to go crazy with the abstractions.
BTW, for some context you might want to look at this earlier thread where I was nice about Go :) https://plus.google.com/107890464054636586545/posts/dVowddBT8AW