I also write a little Go program every day as practice. If you want a sample of some Go. https://github.com/kris-s/daily-go
I also write a little Go program every day as practice. If you want a sample of some Go. https://github.com/kris-s/daily-go
This is a common refrain amongst go proponents and I find it quite distasteful. It either implies those of us who prefer other languages aren't "getting things done" or those who feel productive in Go aren't smart/hard-working/educated/etc enough to "get things done" in other languages. I don't think either is true.
I think a more accurate way to look at Go is that the language, tools, and standard library make decent design trade-offs when your target software is 1) simple 2) network daemon-y or a CLI and 3) going to be worked on by a wide variety of developers. There are lots of problems that fall into that problem set, and it is very nice to have a language targeted at it, but Go is certainly not a good fit for a huge number of software projects. You will be less productive in those cases using it.
gofmt, for instance, is uncontroversial. Taking the decisions about how to format code away from developers and standardizing it is widely seen as a win (a win Python flirts with as well).
Well, there's a lot of other things in Go that have been pre-decided for you, not just the formatting. The net effect is that you don't have to waste time:
* thinking about designing a DSL for your programming problem (DSLs in Go require parsers)
* designing a class hierarchy to express your programming problem
* choosing between event-loops and callbacks or pools of threads
* picking the right associative container library (do I want a red-black tree? a hash table? a trie?) for routine coding problems
These pre-decisions can feel confining, but I think for a lot of developers Go reveals that those decisions were usually a waste of time. When you actually hit a place where you need a red-black tree, it's not that big of a deal in Go to bring one in. You're just not going to do that for your session store or for a simple lookup cache --- which is, I think, what a lot of people who can't stand Go's lack of generics would be doing.
The problem, I have with the sentiment (which I grant is largely me over reading into it) is that a lot of the things people think of as noodling or a waste of time, are the central problems in more complex environments. Making sure your program is correct is very important in some environments. Making it easy to express complex domain knowledge as a subset of a programming language is a huge win in some environments.
That isn't a lack of getting things done, thats just more complex logic requirements.
But in C++, those are decisions you might make in parsing a config file, or in managing a simple table of sessions, or adding an LRU cache to something. You can't get away from the decisions. I have an array of stuff, and I have to decide, "do I want a list, an slist, a vector, or a deque, and what the fuck is a deque?". 98% of the time there is one sane decision that is so close to optimal that it's not worth tinkering with.
In Go, for prosaic, routine code, those decisions have been made for you. You have to go just annoyingly enough out of your way to second-guess those decisions that you almost never do, and you're almost always better off for not having to do it.
I'm currently working on a project (WebRender) in which we keep using the standard library hash table in the first cut of code whenever we need an associative lookup table, and every time we use it it keeps coming up #1 in the profile. Almost every single time. We then have to switch to another, more optimized data structure, and generics really help here so that we can reuse these data structures. In fact, if we didn't have them, we'd probably be sunk.
This just isn't as much of a big deal as people think it is. Go makes it a drag to use a custom container, but it doesn't make it hard, and that might be how it should be!
> This just isn't as much of a big deal as people think it is. Go makes it a drag to use a custom container, but it doesn't make it hard, and that might be how it should be!
I believe you that it wasn't a big deal in your case. But I disagree with your general claim. I think you're extrapolating from your use case to claim that generics aren't important (vital, in some cases). I'm saying that, in my use case, they are.
If the default doesn't work for some reason then I can tackle that problem but at that point it usually is core to the problem I'm working on.
For some people Go is anything but frictionless though. They spend all their time in Go fuming that their favorite abstraction isn't there. For those people my experience doesn't translate.
Otherwise, the go built-ins are usually the "get on with it" win.
It's subjective though. I'd guess that if you're a fan of the suckless style of engineering, go might be right in your wheelhouse and you will probably find it very beautiful if you can accept garbage collection.
The syntax perhaps. In reality there are a large number of concepts and idioms to learn on the never-ending road to really becoming proficient.
Take initialization for example: look at all the edge cases belabored in section 8.5 of the C++14 spec, or even the intricacies of initialization in a simpler language like Python. Now contrast this with how much lexical and conceptual space it takes to describe zero initialization in Go's spec: https://golang.org/ref/spec#The_zero_value
As in other areas, Go's approach here has downsides. (Possibly major ones.) But those tend to be conscious design decisions to minimize the total number of concepts and idioms present in the language.
Also, I don't understand the benefit of being able to learn a language in one day. You can learn how promises work in a single day and then apply that to any language that implements them. With Go, you will learn the language but then have to re-implement promises for every type that you have [0].
Consider the use case of issuing two API requests concurrently and assembling their results. You can do this using the fan-out, fan-in pattern described at http://blog.golang.org/pipelines
Search the page for "func merge". Any time you want to fan out and fan in, you will have to write that block of code for the types of the channels you have, or else use interface{} and lose type safety. So the cost of a language that can be learned in one day is that every single time you perform this very common concurrency pattern, you will have to repeat this code and potentially make errors in the process. And if you want to change how this merge pattern works across your codebase, you will have to change it in many places. What happened to DRY and reusability?
[0] There is a Go promises library, but it uses interface{} for all callbacks and does not appear to have been an active project over the past year. https://github.com/fanliao/go-promise
So, just like VB then?
JS is pretty damn tricky though, I'll give you that one.
It could just be the feeling that Go gets out of your way more than other languages do. (For example, people complain about how much ceremony is involved in writing Java. Go could easily feel like "getting things done" in contrast.)
However, I guess the inability to deeply understand or pontificate about Go is an advantage in itself... forcing your only potential activity to be getting work done.
Also, are you sure that there are more popular Go projects than popular Scala projects?