[I'm a Rust user, and not particularly fond of Go, but...]
Not having great static typing doesn't make it not pragmatic.
Given Go's purpose, it is extremely pragmatic.
One of the reasons Google uses Go is because their employees are often fresh out of college and might not be familiar with the depths of type systems.
If you look at most professional Java/C++ code (starting to see this with Rust too), the features of the language are used to their full extent to create really convoluted APIs (to an outsider not familiar with the language). So, to work on it, one must first become familiar with the intricacies of these languages (this is not as easy as picking up a book, you need experience), and then with how the language is used in context, which is another time consuming thing.
Instead, go trades off some higher level features for compilation speed and ease of learning.
After programming in Go for a week I was able to pick up any Go code -- ranging from the standard library to various other applications, and know what was going on. I cannot say the same about Java or C++ or Rust; generics/templates/virtual/friend/advanced typesystem gymnastics all are used to great extents in the code for a standard library or some large application. one may be able to use the language for your own stuff after a week of learning and hacking, but one will need much more time before they're well suited to contribute significantly to existing codebases.
A course I took recently was taught by a PL aficionado. He knew Rust, Nim, and Go, along with many older languages. Go, Rust, and Erlang, among others, would have worked beautifully for the project topic (concurrent stuff). He made everyone write in Go because he wanted a uniform language for project evaluation, and because Go is something students could reasonably pick up in a week without constraints on their background.
=========================
At the same time, the Go community is pretty awesome. There is a "go way" of doing things, and while it is pretty rigid, that doesn't make it not pragmatic. From my (admittedly limited) discussions with them, they do seem to think practically/pragmatically. There are good reasons for wanting to use Go. These folks know those boundaries, and think practically within them.
Though there might be much to say about the different implementations of generics, I've found them to be easy to understand and use in languages. No type theory required. That has been more like "Oh, so that's the name for that thing/aspect, neat".
If I don't have a problem with that, those coveted master race Google developers should have absolutely no problem with it.
It's not that generics are hard to grok, it's that they get used in a hard to grok way. Wrapping your head around such things gets more and more hard as the app complexity grows.
The base point is that languages like Go let you think of the program at runtime, only. Types are a runtime concept, everything is a runtime concept. Structuring APIs to use compile time safety requires a whole other kind of thinking, one which they may not expect to be uniformly available.
Ultimately it's a choice of whether or not you want to the programmer to think of data and flow (runtime), or metadata (types, compile time). Once you're used to both the difference is blurred. For newbies, the concept of using compile time safety can be daunting.
Right, don't have to think about compile time. Instead they sometimes have to think about post-compile time[1], i.e. code generation. Now you don't have to think about those weird bracketed capital letters. Just take care to check where you have comments[2] that happens to include directives to some external tool.
With how Go programming seems to work for some people, I can perfectly well imagine a system with commands that do code generation as a hook for other commands, or by 'listening to the file system' for changes in certain files. That could get out of hand pretty easily. And yeah, one can say "anything can be taken too far". Just like you said about generics. The difference might between having well-encapsulated and behaving mechanisms that does most of what you normally would need. As opposed to a "simple" system that just pushes the problem to another level, in more ad-hoc ways.
[1] I honestly don't know if the code generation typically is pre-, post-compile or a mix of those two. It's too complex for me.
[2] I thought single-line comments was supposed to be a safe haven...
Not everyone uses codegen or other tools. You can write generic-ish code in Go which is just runtime checked via vtable pointers (interface objects).
And of course, the loss of static checking means that one has to write more tests for mundane things. But again, designing tests requires "runtime thinking", designing statically checked APIs requires "compiletime thinking".
Well, variance can be hard for many to grock. The combination of generics, mutation, and subtyping is problematic, complicating nice feature like type inference. I can see why Pike and company left it out, though I think it's quite feasible to fix their problems.
Not having great static typing doesn't make it not pragmatic.
Given Go's purpose, it is extremely pragmatic.
One of the reasons Google uses Go is because their employees are often fresh out of college and might not be familiar with the depths of type systems.
If you look at most professional Java/C++ code (starting to see this with Rust too), the features of the language are used to their full extent to create really convoluted APIs (to an outsider not familiar with the language). So, to work on it, one must first become familiar with the intricacies of these languages (this is not as easy as picking up a book, you need experience), and then with how the language is used in context, which is another time consuming thing.
Instead, go trades off some higher level features for compilation speed and ease of learning.
After programming in Go for a week I was able to pick up any Go code -- ranging from the standard library to various other applications, and know what was going on. I cannot say the same about Java or C++ or Rust; generics/templates/virtual/friend/advanced typesystem gymnastics all are used to great extents in the code for a standard library or some large application. one may be able to use the language for your own stuff after a week of learning and hacking, but one will need much more time before they're well suited to contribute significantly to existing codebases.
A course I took recently was taught by a PL aficionado. He knew Rust, Nim, and Go, along with many older languages. Go, Rust, and Erlang, among others, would have worked beautifully for the project topic (concurrent stuff). He made everyone write in Go because he wanted a uniform language for project evaluation, and because Go is something students could reasonably pick up in a week without constraints on their background.
=========================
At the same time, the Go community is pretty awesome. There is a "go way" of doing things, and while it is pretty rigid, that doesn't make it not pragmatic. From my (admittedly limited) discussions with them, they do seem to think practically/pragmatically. There are good reasons for wanting to use Go. These folks know those boundaries, and think practically within them.