Email or username:

Password:

Forgot your password?
Hrefna (DHC)

Some notes on #golang, this is purely my personal opinion and not representative of my employer's take in any way.

When golang was first released there were several things that Rob Pike in particular seemed to think about it:

1. A replacement for C++ and Java for server systems

2. Good for large, scaled engineering teams. The sorts of teams with lots of moving parts

3. Effective for large amounts of data processing, especially the sort you do in web environments

go.dev/talks/2012/splash.artic

1/

41 comments
Hrefna (DHC)

They also made some assumptions in the kind of workflow they were trying to work with/encourage

1. They didn't like IDEs. They largely come from a group of devs and an era of devs who didn't (though I wouldn't say this was necessarily a common take at google at the time)

2. They _did_ like writing data structures. You feel very productive when writing data structures.

3. They were assuming something like a controlled monorepo for development

4. They wanted to optimize for training time

2/

Hrefna (DHC)

Basically at the core of it they wanted to optimize the development loop:

1. Make a change.
2. Compile.
3. Test.
4. GOTO 1.

I'm personally of the view that they wanted to optimize the development loop for someone working predominately from the command line in essentially vim, without a language server. I know a bunch of devs like that and this reminds me of them in a lot of ways.

3/

Basically at the core of it they wanted to optimize the development loop:

1. Make a change.
2. Compile.
3. Test.
4. GOTO 1.

I'm personally of the view that they wanted to optimize the development loop for someone working predominately from the command line in essentially vim, without a language server. I know a bunch of devs like that and this reminds me of them in a lot of ways.

Hrefna (DHC)

Early versions of Go outside of Google had no package manager to speak of and it _still_ has a relatively weird stdlib. It made assumptions about your development environment that largely were true at Google, but nowhere else.

The early gen garbage collector also wasn't really all that and had weird pauses that were difficult to debug. There was a nice enough concurrency model, but it wasn't earth shattering and it didn't solve any of the actual hard problems to speak of.

4/

Hrefna (DHC)

Many of these issues have improved with time, but what happened next was a bunch of exec types LOVED golang. They could read it easily. They saw it as The Future™.

I was told repeatedly by multiple exec-types that this would displace Java and C++. That this would integrate better with the world. That it would come with a free pony.

This built a lot of resentment in engineers who had to deal with the execs telling them "THIS IS WHAT WE ARE DOING NOW" on the one hand and reality on the other 5/

Aranjedeath

@hrefna absolutely shot themselves in the foot by capping max open files at 1 million at the runtime level, I had to walk away from a perfectly good piece of software over it

Hrefna (DHC)

But beyond that, if you were working on a large software project in Java or C++ you likely had a lot of very powerful tools in your IDE. You had a strong SDK and tools that worked with it.

You had a robust development environment. You had powerful frameworks that had been battle tested for years and dependency managers that, while everyone complained about them, they mostly _worked_ and their quirks, while not solved, were also not blockers for most work.

So for a lot of us it was… okay? 6/

Hrefna (DHC)

We had incremental compilation, so the only time you had to do a full compile was on the CI/CD infrastructure. It was often still painful, but we were finding more and more ways around it with good build tools.

We had autocomplete. We had extensive refactoring tooling.

We had subtypes and a lot of strong language features that made it _easier_, not harder, to read on our large software projects.

What's more, there was a lot of looking to the future.

7/

Hrefna (DHC)

Developers were graduating with better and better knowledge of the systems we worked with. There was one of the big pushes in category theory that seems to happen every few years going on. The developers who _had_ graduated _years_ ago weren't leaving industry but they _were_ getting older. People were looking at concepts like pattern matching and fp.

Go was explicitly made for new graduates, but developers are only new graduates (if they are graduates at all) for a very short period of time 8/

Hrefna (DHC)

So along comes go and in every respect it seems to be looking backwards, but not in the way that the industry rediscovers actors every ten years or so. It wasn't rediscovering the past, it was flat-out tacking that direction.

But. A language existed that was sometimes used for servers but was used for a _lot_ of utility scripts and applications and that a lot of people struggled with for large projects. Where there were already libraries for CSP but they were used but inconsistently. 9/

Hrefna (DHC)

Python developers often really liked Go and SREs who had to maintain major python projects REALLY liked go

There were IDEs for python, but they weren't at the level of maturity that Java or C++ had. They were dynamically typed and so a little type safety often felt like an improvement rather than a step backwards. The fast compile times were appealing, and the style guide appealed to a group who believed "there's one obvious right way to do it"

We saw a lot of go taking over in that space 10/

Hrefna (DHC)

Basically: the execs notwithstanding, most engineers didn't see go as a silver bullet but as a nice enough tool in the toolbox, especially for writing, say, command line utilities or simple web servers.

C++ and java devs weren't willing to sacrifice the performance or more sophisticated typing, packaging, etc. They had tools to reduce the complexity they had to deal with and go seemed to shove all of that complexity at them and say "BUT THIS IS A SIMPLER WAY OF DOING IT."

11/

12 Lilith it/its𒀭𒈹𒍠𒊩 replied to Hrefna

@hrefna in our experience with golang, we only hae one objection:

Who, in their fucking right mind, decided that `try: catch: finally:` blocks were bad? like, fuck sake

Hrefna (DHC) replied to 12 Lilith it/its𒀭𒈹𒍠𒊩

@12 heh, I know this is rhetorical, but I actually can take a pretty reasonable stab about where that aversion comes from if you'd like. :p

12 Lilith it/its𒀭𒈹𒍠𒊩 replied to Hrefna

@hrefna fucking please. There are two few languages that we can get our head around, and golang is, almost, one of them. except for that bit.

Hrefna (DHC) replied to 12 Lilith it/its𒀭𒈹𒍠𒊩

@12 So it comes out of a combination of type theory, a counter-culture reaction to Java, some thoughts out of structured concurrency, and Rob Pike et al's desire to "simplify" the language by pushing complexity onto the developer who is writing the code.

It works a bit like this:

When you call a function it will have a return value with an associated types. Errors are just another kind of type, so if your program has a type `T` then with the exception it becomes `T | IllegalArgumentException`

12 Lilith it/its𒀭𒈹𒍠𒊩 replied to Hrefna

@hrefna our brain learned:

```
try {
thing thing = new thing();
thing.DoTheThing();
};
catch (thing.CantDoTheThingException e) {
printf('can\'t do the thing. Got %s (error code %d)', e.type, e.code;
}
```

Hrefna (DHC) replied to Hrefna

@12 Try-catch blocks evolved from how these errors often cluster and how we want to intercept them and wanting to avoid eight million if-else blocks. That's the plus side.

The downside is that the error can come from anywhere in the block of code and anywhere in that block of code's call stack. It may have weird handling requirements (like Interrupts) or may be a nop, or it may never happen in reality.

12 Lilith it/its𒀭𒈹𒍠𒊩 replied to Hrefna

@hrefna we've found ChatGPT helpful, yes, we know, in figuring out golang withot fighting with tutorial sites. We're like, ok, show us how to do this. And from that, we can see how it does the thing and do the thing ourself like

Hrefna (DHC) replied to 12 Lilith it/its𒀭𒈹𒍠𒊩

@12 I actually like the AI tools for this sort of thing, personally. Sometimes they can help illustrate something that is difficult to see otherwise.

I've used bard to learn cypher and a few other things like that because while its coding is atrocious it can often help with the things no one talks about.

12 Lilith it/its𒀭𒈹𒍠𒊩 replied to Hrefna

@hrefna right! And like tutorial sites are like, here is this simplified thing that you don't want to learn. We learn best by seeing how others do it. Sidenote: good gods software *engineers* are scary. build systems and test cases and dependency management and release tagging and shit, where we're from you're lucky if you get a `cc -o dothething -I./src/common -I./src/thinglib thinglib_core.c thinglib_tui.c dothething.c dothething_plugins.c`

12 Lilith it/its𒀭𒈹𒍠𒊩 replied to Hrefna

@hrefna we're a software hacker in the 1980s unix sense. It plays right hell with our atempt to get a job, too

Hrefna (DHC) replied to Hrefna

@12
Java attempted to deal with this with checked exceptions, which made a lot of people angry and are now widely regarded as a bad idea.

A lot of languages have this pattern, but it doesn't feel nearly as contrives or ugly as it does in Go. In functional languages (Scala's Try blocks, Ocaml's Result and Or_error systems) you get nice first-order structures, so your code becomes:

(do a thing).map(
do something else
).map(
do something something else
).iferror(
handle it!
).getValue

@12
Java attempted to deal with this with checked exceptions, which made a lot of people angry and are now widely regarded as a bad idea.

A lot of languages have this pattern, but it doesn't feel nearly as contrives or ugly as it does in Go. In functional languages (Scala's Try blocks, Ocaml's Result and Or_error systems) you get nice first-order structures, so your code becomes:

12 Lilith it/its𒀭𒈹𒍠𒊩 replied to Hrefna

@hrefna yeeeesh. We feel like as a kid we learned like a weird bastardised combination of C and Python? and that has just absolutely stuck with us, and then we learned C#......... of the terrible projects we created in C# we hall not speak

Hrefna (DHC) replied to 12 Lilith it/its𒀭𒈹𒍠𒊩

@12 My first language was hypertalk, which is a bizarre language but also a very cool one.

It's _really_ hard to shake early paradigms with languages. I'm generally of the view that languages are easy, but learning the ecosystem is difficult and learning paradigms is difficult

I've seen programmers with decades of experience segfault entirely when running into a different paradigm.

So you aren't alone in that, and in this case they picked up none of the things that makes that pattern… work.

12 Lilith it/its𒀭𒈹𒍠𒊩 replied to Hrefna

@hrefna yeah, the paradigm we learned was... very C-style. Very very C. Not that we can hack it in C; the only thing we ever wrote in C were some truly dirty Linux kernel hacks

Hrefna (DHC) replied to Hrefna

@12 But in go you:

a) Lack generics
b) Lack any of the functional patterns
c) Lack pattern matching
d) Are using a lot of the patterns for programming that are common in the C-derived world.

So you end up with code that is extremely verbose and contains a lot of if-else-if-else-if-else calls.

Which even for someone who prefers to avoid try-catch blocks in languages with good semantics for it makes me _really_ twitchy ^^;;

Hrefna (DHC) replied to Hrefna

@12 Oh, and one more note on this, in the languages with operator overloading this becomes downright _clean_. It becomes something like:

RunSomething >>| do_something_with_result >>| do_another_thing >>= deal_with_errors |> add_callback

Now it can even be concurrent and still nice and clean, with no changes to the code.

Which is why a lot of people like this pattern, but it does involve a different way of thinking, and I'd argue its absence from go is keenly felt.

Hrefna (DHC) replied to Hrefna

The execs insistence here was especially painful for _data engineers_ because our lives revolved around taking data from one place, applying a series of transforms to it, and putting it somewhere else. The steps were often very similar to each other but with differently shaped data, so we could reuse a lot of code in a lot of cases.

Do you know what languages make that easy?

If you answered _anything with parametric polymorphism/generics_ you are most likely correct.

12/

Hrefna (DHC) replied to Hrefna

I want to emphasize: None of this is really a flaw in Go _per se_ (well, some aspects may be, but I'm not talking about that right now). Go has a pretty strong core and it works well in that area. There are a lot of go programmers, and a lot of the issues I'm describing have been smoothed over with time, and execs have become less… enthusiastic.

It does mean I think that—for what Go was initially being advertised for—a lot of people who were already in that space found it difficult.

13/

Hrefna (DHC) replied to Hrefna

It works "well enough" in that space but it is just "well enough." Its advantages were muddled when compared to languages like Java, C++, and C# and it wasn't _clearly_ better, which made adoption difficult against those languages.

It's still managed at points, but it's because a team evaluates the tradeoffs and finds that it fits, not because it is head and shoulders better (like, you know, everyone in industry for more than six months would expect).

14/

Hrefna (DHC) replied to Hrefna

It goes back to: there are no silver bullets. You can't just rub a programming language on top of bad practices and get a good result.

You are going to get a bad result regardless of what language you are writing in, and safeguards can backfire in a large enough project because they make things difficult to reason about or adequately test.

Anyways, I may have more to rant about on this eventually, but I'll leave off for right now.

15/TBD

mnl mnl mnl mnl mnl replied to Hrefna

@hrefna one thing that golang “kind of” is a silver bullet for is not having to worry about the concurrency model with libbashing an app together, which was my main pain point in c++ and python (when I used to do Java I wasn’t writing systems so dodged that problem) and was something not entirely settled the last time I built something in rust.

The “developer hostility” is felt in the terse tools as well. It’s getting better, but compared to rust or JavaScript it feels of another century.

סייג׳ replied to Hrefna

@hrefna interesting read. I am a "hobby programmer" - as in I write really small projects once in a while for my own enjoyment/use, and personally I really love Go. It feels like I have more control than python but much less of a hassle than C. so I think the statement made here is very correct, at least anecdotally.

Tim Panton

@hrefna the ‘one right way to do it’ is a direct contrast to scala -which I wanted to love- where there are 5 right ways to do it and every shop has its own style guide, making learning the language as an itinerant contractor impossible. I ended up going back to modern java (for preference) and learning golang for new customers.

Hrefna (DHC) replied to Tim

@steely_glint I programmed in scala seriously for several years. I have been on scala projects that were _great_, easy to read, cleanly coded…

…and also ones that aren't

IME you need really tight discipline to make it work and it helps if you have a small team that's all relatively senior and dedicated to quality. When I've had that, I've really seen the elegance

Whenever I see a large project that doesn't check those boxes and managed to not be an eldritch nightmare I can't help but applaud.

Ben Evans

@hrefna A detailed & nuanced take that pretty closely matches what I observed of Go from over here in my mostly #Java / #JVM world.

Chris Laprun

@hrefna @kittylyst my main take, which I think matches yours, from my Go experience, is that Go is optimized for reading while Java has become optimized for writing

Go Up