The true is that I had never been so productive writing code. The friction from what is in your head and the code is almost 0.
It is true that I ended writing a few functions that were there only because the lack of generics, the type system and other stuff being "built-in". But at the end, I think it was an order of magnitude less often than I was expecting it to. I was wrong.
But I think that the "friction from what is in your head to code" probably betrays that you weren't settled in a previous language? I only say this because I have zero friction writing C++, and have to think mildly backwards when it comes to C# or Java, and definitely Objective-C. Even PHP is like simplified C++ to me, so I write everything like it is a dumbed-down dialect of C++.
I suppose it is just what some people find comfortable.
I had the same feeling as the user you're answering to. And I have used quite a bunch of languages I've been quite productive with (C, C++, PHP, Python, Java, Ada), but I've never felt with these languages as little "friction" as with Go.
I mean, that language is so dumb that you don't have to think about the right way to do stuff. It's obvious. Boring, sometimes verbose, but obvious. It doesn't stand in the way between me and the problem.
I am not only talking about the strict compile checks. I am talking about that extra thinking in the ten ways you can design it and how it should be done in "proper" Rust.
And the friction is not only in the language, but also in the standard library. A language that comes with XML/json marshal/unmarshal plus a quite decent http client/server framework covers most of what I need to do.
I am sure if Rust had included in the standard package http/xml/json it would be far more popular. I understand the voices that say "It does not belong there", "the language is not targeted at that". Fine. But then I found myself having not much user for the language, even if I loved the idea/theory behind it, plus that I could not get comfortable thinking in it.
* Transforming a collection means doing boring for loops instead of one-liners. * interfaces/duck typing is great. But hey, []interface{} does not fit into interface{}. * Structs with fields are encouraged, but there is no uniform Uniform access principle and that sucks. * etc
But definitely, my own "science" confirms that it turned to be out less of a problem (for my own usage) compared to better languages with more friction.
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.
If I don't have a problem with that, those coveted master race Google developers should have absolutely no problem with it.
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.
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...
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".
Why do people keep on saying that? Would people say javascript is for the pragmatic crowd because jsfiddle exists ? no
Go is a badly designed language period. the type system forces devs to write runtime type assertions which should be the job of the compiler thanks to parametric types, if go designers knew one or 2 things about types. The fact that Go dismisses 30+ years of type theory isn't pragmatism. It's ignorance.
Nobody would call PHP pragmatic yet even PHP is more expressive.