I think there's a great value in code being straight forward and simple and that is very much not appreciated among many programmers.
A good language enables you to "compress" your code without making the code flow impossible to follow.
A bad language encourages you to obfuscate the flow of the program using wacky abstraction techniques.
Go doesn't exactly hit the sweet spot for semantic compression due to lack of compile time programming (aka generics?), but it does a good job of making the flow of the program pretty clear.
IMO Go has poor primitives that make even straightforward code needlessly complicated. Slices are probably the worst. Compare Python's way to inserting a value into a list:
WTF?! Isn't the point of an abstraction to make simple what is complex? Insert into a list should always be like the python example. If go's standard list doesn't have that, maybe it's time for someone to write a better library.
The insertion operation on slices is expensive and is not recommended to be used frequently.
If you use it frequently, please rethink and redesign your data structure, for example, use a list instead.
I tried using Go this weekend and basically just abandoned it when I learned that it only had 'generic's for three built-in types and other than that you are forced to essentially dynamic cast everywhere.
I just don't get the appeal. Go seems a lot like what you'd get if you just removed every language feature that anyone has ever complained about; for good reason or not.
It seems like the domains where Go is used often don't make heavy use of custom containers or data structures, so that makes the pressure on the language makers lower than it would otherwise be.
I venture to say that if you are casting/converting everywhere, you are likely doing it wrong. An interface{} says nothing. It should generally be avoided. However, I do find this to be a pain when working with numbers. Floats and ints mixed up is not fun. Python is so vastly easier to work with in that arena.
In Go, if you need a container which is not a built-in map or array, you end up casting to interface{}, because that's the only reasonable thing your container can accept. This is clearly not "doing it wrong", and it's an extremely common use case.
A good language enables you to "compress" your code without making the code flow impossible to follow.
A bad language encourages you to obfuscate the flow of the program using wacky abstraction techniques.
Go doesn't exactly hit the sweet spot for semantic compression due to lack of compile time programming (aka generics?), but it does a good job of making the flow of the program pretty clear.