Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I picked up the new Go book (gopl.io) and have had a lot of fun going through it. The prevailing feeling of Go is "getting things done".

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



> The prevailing feeling of Go is "getting things done".

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.


I agree with you, but there is something to the argument; it's just poorly phrased as "getting things done".

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.


I think that falls into my use case of "simple". If you don't need to make those kinds of decisions, then by definition your problem set is simple (at least from a business logic point of view, even simple business problems get complex at scale).

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.


I think you're missing a subtlety of my argument. I'm not saying you never need to pick a container that isn't a simple hash table, or design a DSL, or roll your own event loop, or design a hierarchy of abstractions. I've done all of those things in Golang --- even the event loop!

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.


> 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.

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.


Again, I'm not arguing that we never need custom containers.


I'm saying that some projects need custom containers all the time—to the exclusion of the built-in ones—and need to reuse the implementations of those containers.


So did we! We didn't use Golang's maps to implement limit order books; we used a red-black tree. We did not build our own, nor did we find a red-black tree that was designed for order books.

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!


And you had one data type that you used with that red-black tree, so you didn't mind not being able to abstract over the types of objects you were placing in the container. But we have lots of data types that we reuse for freelists and other types of containers. We don't want to have to reimplement that code for every single type we want. That's where generics save us.

> 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.


I sum this phenomenon up as "frictionless development". I don't have to stop and make a decision about something not core to the problem I'm working on while writing code.

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.


Not a big fan of gofmt, but oh well. (I prefer more whitespace, both spaces and newlines, than K&R formatting would like)

Otherwise, the go built-ins are usually the "get on with it" win.


It's true though. Go has a small number of language features, and they are only the simplest ones. It can be learned in a day. Other languages like JS, Ruby, and Python have a big fixation on figuring out the prettiest syntax for stuff (JS promises and chaining etc, "Pythonicness", and Ruby's incessant cuteness). In Go, you can't really make things pretty, so you just bang out code.


I don't know that "pretty" is the right description. High quality, well made, canonical C has a certain beauty to it and Go tends to offer a degree more on that vein. I personally find that much of the js, Python, and ruby "beautifying" is related to compactness more than being easy for the next guy to view the correctness of or understand.

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.


>> It can be learned in a day.

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.


Yes, but there's a kernel of truth there. I wouldn't say I managed to learn Go in a day, but after perhaps six months using it I was much closer to mastering Go than to mastering other languages I'd been using for years. Go's road to proficiency is a shorter one, there's just less stuff to cover.

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.


Promises (which aren't limited to JS) are about far more than pretty syntax. Promises and promise combinators give you guarantees about your code, such as "no promise will ever execute both its success and failure callbacks" and "of the callback that is executed, it will never be executed more than once," and "once a promise is resolved, it's state cannot ever change."

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


>Other languages like JS, Ruby, and Python have a big fixation on figuring out the prettiest syntax for stuff (JS promises and chaining etc, "Pythonicness", and Ruby's incessant cuteness). In Go, you can't really make things pretty, so you just bang out code.

So, just like VB then?


Or .bat file master race.


"Ruby's incessant cuteness" is a first class feature of the language in practical environments, but not of the language itself, in my opinion. While I can knock python for whitespace, and not a whole lot else, I think ruby is probably the most "learn in a day" language I've ever experienced. Without any background in strongly typed language or anything else C-like, Golang actually took me several days of work just to understand paradigms like slices, which were pretty foreign to someone who only worked in dynamically typed language.

JS is pretty damn tricky though, I'll give you that one.


I think a difference here is not that people don't get things done with other languages, it's that the language was designed with that as a first class metaphor. (Whether or not that is true I can't say, but that's the feeling the poster gets.)


You are over analyzing that phrase.


Granted.


> 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.

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.)


"Getting things done" is quite accurate considering large number of popular Go projects in short time compared to allegedly better design languages ( Scala, Rust, Haskell, D, OCaml etc..)


You are mixing productivity (getting things done), quality (better designed languages) and popularity (large number of projects) in the same sentence, but you generally cannot find causal links among them.


In Haskell a lot of it is due to people thinking they need to deeply understand everything before cranking out code. It's like trying to understand music theory before strumming some guitar strings... actually it's probably something less useful than that.

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?


That may also have to do with the massive push behind it.


that would mean javascript is better than go for GTD ;)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: