Don't get me wrong; there are some good things about Go. I like the syntax of types and declarations. The concurrency model is interesting (although I am no expert) and timely. Function closures are cool.
My criticisms of Go concern its type system. Modern languages tend to be complex, and anything that helps to keep them simple and uniform is good. But Go's type system is anything but simple and uniform.
These comments are based on my reading of the Go Language Specification around 29 August 2011. I have never written a Go program.
Go's predefined types are built-in, not defined in libraries. This allows the compiler to do things for those types that it does not do for user-defined types. In particular, some operations on the predefined types are operators, but you can't define operators that apply to user-defined types. Again, there is a nice syntax to convert between the predefined types (int to float and so on), but not between user-defined types.
I feel insulted when the designers of a language give nice features to their types, but don't let me use them on my types. I feel as though they are saying: "We are important people, and our types are important types; but nobody cares about your types, you stupid worm." But it's not just a question of hurt feelings. It means that whenever some important new type comes along (for example, "complex") it has to be built-in, because the features it evidently needs are not available to user-defined types.
Of course, in the end an operation like integer addition has to be built-in, because it is implemented by hardware. But if you look carefully, only the implementations of the features of built-in types need to be built-in; their interfaces can be defined in the language, if the language is well-designed. Defining the interfaces of predefined types in the language is good for the programmer too, since the specification is unambiguous and does not have to be inferred from the language manual.
Go has three built-in generic types (arrays, maps, and channels) and no user-defined generic types. At this late date, and with the well-known history of C++ and Java to learn from, this is inexcusable.
Go allows you to include a type as an anonymous field of a struct, and then the type's interface is included in the struct's interface. A call on a function of the included type's interface is passed the address of the anonymous field as the equivalent of self. (Read about it in the manual here.)
Although the manual does not use the word, this idea is well known under the name "delegation". Delegation is very similar to inheritance: it puts the same fields into a struct, and the same methods into its interface, as inheritance puts into a class. But it's not the same. For example, there is no method redefinition with delegation.
Bjarne Stroustrup discusses delegation in some detail on pages 272-273 of his book "The Design and Evolution of C++" (Addison-Wesley, 1994). He says: "I tried out an implementation on a few users ... every user of this delegation method suffered serious bugs and confusion". I have never used delegation myself so I am not going to endorse his opinion. My point is that it is different from inheritance and one can't just assume that it is as good.
I am not talking here about defining an interface and implementing it with a concrete type. That is a simple, common form of inheritance, well known to be well-behaved. Delegation is different.
My favourite programming language is statically typed and offers both genericity (including constrained genericity) and inheritance (including multiple inheritance). The interfaces of all types are completely defined by classes, although inevitably some of their implementations (for int and so on) have to be built-in. The typing rules include subtyping and are simple, uniform, and safe.
I'm still waiting for it to come along. It's strange: for twenty years now we have had the type system (Cardelli and Wegner, 1985) and the compiler technology (C++, 1992), but we don't have both in one language.