Live data from Hacker News

I want off Mr. Golang’s Wild Ride (2020)

fasterthanli.me

301–310 of 477 posts

Re: I want off Mr. Golang’s Wild Ride (2020)

#301

Earlier quoted context omitted.

Errors as return values is only acceptable for code that is so performance-sensitive that you aren't allowed to do dynamic memory allocations. For everything else, conditions+restarts are the correct answer, because errors-as-values restricts you to a single error-handling strategy and couples high-level code to low-level code as a result.

> Errors as return values is only acceptable for code that is so performance-sensitive that you aren't allowed to do dynamic memory allocations. Exceptions-based code can be zero-cost, if no errors occur, at an increased error-case cost. Using error values pessimises this, and increase branch prediction load (as every callsite is now a branch). So in the common case where errors are extremely rare, exceptions-based e…

This is an extremely good point - thank you for your correction!

Re: I want off Mr. Golang’s Wild Ride (2020)

#302

Earlier quoted context omitted.

Errors as return values is only acceptable for code that is so performance-sensitive that you aren't allowed to do dynamic memory allocations. For everything else, conditions+restarts are the correct answer, because errors-as-values restricts you to a single error-handling strategy and couples high-level code to low-level code as a result.

Fun history fact: Rust had conditions, a very very very long time ago, but folks didn't use them and found them vaguely confusing, so they were removed.

This doesn't mean very much. Most people find the Rust borrow checker "vaguely confusing" (if not very confusing), and most people also wouldn't use it were it not strongly suggested by both the compiler and the community ("suggested" as unsafe Rust exists, but you of all people are aware of that).

Conversely, I understand condition systems, and I'm not a very good programmer. (I've tried and failed to learn Rust once already) That's a pretty low upper bound on how hard they are, especially relative to advanced features of languages like Haskell.

We're very fortunate that programming language design doesn't advance solely by giving people more of what they already use.

Re: I want off Mr. Golang’s Wild Ride (2020)

#303

Earlier quoted context omitted.

I don't think Go gives you freedom, actually. There aren't any good standard library functions for dealing with badly encoded unicode for file names, for example. Instead, Go provides what the language designers considered solutions to most problems. Window not having Unix permissions? Just fake a bunch of them. Path not valid unicode? Probably not a problem. As long ad you agree with the way the Go designers think,…

The counterpoint is "your filenames shouldn't be badly-encoded unicode." In other words, "If `ls` can't render it, it's a bad filename. Rename the file." (This does mean that Go is constraining the set of problems it's easy to solve with it. But that's the nature of programming in general... We decide what problems need to be easier to solve at the expense of putting some problems outside the "sweet spot" and requiri…

If `ls` can't render a filename that is legal under the POSIX specs, there are two possibilities:

- `ls` is wrong and should be fixed.

- The specs are wrong and should not allow filenames to be arbitrary bytesequences.

The third option ("The user is wrong even though they did exactly what was in the spec") is just unsatisfactory because it self-contradicts.

Re: I want off Mr. Golang’s Wild Ride (2020)

#304
post #241

I liked the article. I think it was really well written and these are great points. So if not Go, then what's the alternative? I too am starting to feel a bit burnt out by some of Go's deficiencies, but one of the things I really like about Go is its concurrency model. What other languages have great concurrency models? Please keep in mind that I want to keep things simple... having a single binary to deploy is incre…

Nobody will suggest Java, but honestly Java. Java has pretty great flexibility when it comes down to concurrency. It sets the standard which all the other languages have to compete with. Apart from that, I like languages and frameworks that scale out of their box and into the world of distributed systems. Elixir is very cool, because the concept of distribution with message passing is built into the core of the langu…

I'm going to sound very elitist, but there is 0 chance I'm going to use Java. Aside from my own bad experiences with Java in a professional setting, .NET Core is now a thing, and I'm actually very experienced with C#, so I'd rather just use C# at that point rather than become proficient with Java and the JVM.

Re: I want off Mr. Golang’s Wild Ride (2020)

#305
post #227
post #157

Earlier quoted context omitted.

I've done pet projects in Haskell, Ocaml, Racket, Rust... Now I'm learning Zig... I've worked for years with Java, Python, Javascript/Typescript... Use to work with Z3... Tried plenty of different stuff. After years my conclusion is that If I want to get a job done I'll choose Golang. Hands down the best productivity programming language nowadays. GC for memory management and productivity, explicit, easy to read, har…

I've done all kinds of stuff too, and agree that Go is pretty good to "get things done", especially networking. But I don't know about best. Maybe ten years ago when a static binary was important, but now that everything is deployed as a container, that's off the table and things like Python or Kotlin are equally deployable, but way easier to use. Nowadays, if you _really_ need a single binary, you probably also need…

I've been developing Python professionally for 15 years, including almost a decade of deploying to containers. I think Go is much easier to use (especially in a container environment):

1. Static types make it much easier to read and write code for even a single individual, and the benefit scales superlinearly as the contributor count and code base age increase. Go also has a ton of other tooling which just outclasses Python equivalents for both simplicity and performance (e.g., profiling tools, and even things like gofmt vs black where the former is way faster)

2. Because Python is so slow, even medium sized test suites take a long time to run. You end up having to triage your test suite to keep CI times reasonable. This just isn't a problem in Go (unless you're doing something I/O bound).

3. Python dependency management still sucks. If you want reproducibility, it takes ~30 minutes just to resolve dependencies for relatively small-but-not-toy-sized projects. This obviously kills your CI times, and there aren't great workarounds except to forego dependency management altogether. Go builds are nearly instant in most cases (assuming you have build caching enabled in CI) and still far better than Python builds in the worst cases. Python also depends a ton on C, so cross compilation is basically impossible (whereas it's trivial in Go) and simply building for any non-mainstream platform is going to entail a whole bunch of work (C projects typically make sweeping, undocumented assumptions about their build environments and targets).

4. Being able to make small artifacts is surprisingly important. When your container image is hundreds of megabytes, you feel it in your iteration loop (especially if you're in a "site down" situation and your iteration loop involves rebuilding and deploying containers to production to restore service). It also means your services can't scale up as responsively, and if a container gets bounced (and scheduled onto another node) it implies longer downtime before that container can carry load again. Similarly, rolling back from a bad deploy can be almost instantaneous if your images are small. Go has the advantage here because it can build on scratch images and because it doesn't need to ship the complete source code (native compilation prunes unreachable code, and binary machine code is considerably more compact than unicode source code).

5. If your development environment is Mac or Windows, Docker kind of sucks for Python development because you'll want to mount your source code volumes into the container, but Docker for Mac/Windows runs the container in a Linux VM with a process that marshals filesystem events back and forth over the guest/host boundary consuming virtually all of the CPU allocated to the VM. In Go, you don't mount the volume at all, rather you just build the image from scratch or you rebuild the binary within the image (or outside of the image and copy it in). You can viably use something like `docker-compose build` as part of your iteration loop with Go.

6. Distributing CLIs via container images makes for a crumby end-user experience, and if you don't distribute Python via container images. Something like shiv mostly works, but there might still be dynamic dependencies that users have to include (iirc, we ran into this with graphviz and a few other libs). Go binaries Just Work.

> Cramming an entire GC and runtime into the executable doesn't seem much different than building a container to me.

A Go runtime (which includes the GC) is just a couple of megabytes. Slim python base images are 60mb compressed.

Re: I want off Mr. Golang’s Wild Ride (2020)

#306

Earlier quoted context omitted.

I don't think "screen real estate" is the right argument here. The problem is just that every line creates cognitive load and there's a tradeoff between concision and descriptiveness. A language with piles of syntactic sugar and magic gets it wrong with too much concision and can read like line noise when it gets overused. Go goes the other way though and makes it way too verbose and just makes it difficult to read t…

I disagree. IMO, there's much more cognitive load in parsing dense, "minified" code than there is in scanning code whose control flow mirrors its visual structure. Humans are very good at seeing visual structure (which is why we tend to indent, split code across lines, and other syntactically insignificant usage of whitespace). By convention in most mainstream programming languages, this visual structure mirrors code…

I don't think not handling errors after every single method call, makes the code dense. Its just way easier to read. 99% of the time you're just going to wrap the error in your own error and return so why not just have a single place that does that?

Re: I want off Mr. Golang’s Wild Ride (2020)

#307
post #186
post #98

Earlier quoted context omitted.

Having to write the same code several times with minor changes because of a lack of abstraction is a lot of fun.

I don't know how people can say go "gets out of the way". Go makes me write dozens of lines of code to do something simple that in an any modern language takes a few. It doesn't get out of the way, it gets in the way constantly. I'm constantly thinking in any modern language I can just do X, but in Go with its myriad missing features I have to sit and think about how I'm going to do it with just loops and if statemen…

Most programmers aren't bottlenecked by keyboard proficiency, but rather by dealing with poor tooling or gratuitously complex programs ("terse" doesn't entail "simple", and very often it's the inverse).

Re: I want off Mr. Golang’s Wild Ride (2020)

#308
post #275

Earlier quoted context omitted.

>because it prevents you from building abstractions, Replying to just this part of your comment, but building abstractions can be as much a source of new complexity and cognitive overhead as it can reduce them. I think Go is wise to be on the side of less abstraction, because most of the abstractions it makes hard end up hurting more than they help. >What an extremely convenient template to dismiss any nuanced argume…

There's nothing stopping you from building bad abstractions in Go, and I find it pretty common. Here's an example: Debug(msg string, keyvals ...interface{}) The keyvals interface assumes you are passing in both a key and a value but if you don't, it doesn't work correctly and in fact in our code I think it blows up.

Definitely. Go is not the last word in the conversation on programming language design, and it hasn’t solved the problem of prohibiting harmful abstractions. But I do think the conservativeness around abstraction is an improvement, at least culturally, over the way many language communities view software development.

Re: I want off Mr. Golang’s Wild Ride (2020)

#309

Earlier quoted context omitted.

Of course. I wasn't trying to imply anything to the contrary. But given the prevalence of exceptions, if Go's error handling is performing on par or better, then it seems pretty ridiculous to characterize Go's error handling as "shit". Don't worry Steve, I think Rust's error handling is pretty cool!

I do agree that exceptions feel like the worst of the various bits of the problem space, to me, but just to be extra clear about it, I have never written a significant amount of Go, and therefore don't really have a very strong opinion about its error handling. And error handling is such a huge and interesting problem space! I've long wondered about why I didn't like checked exceptions in Java but do like errors as v…

I'll take checked exceptions over Go's multiple return values error convention any day.

Re: I want off Mr. Golang’s Wild Ride (2020)

#310
post #125

The author fundamentally misunderstands language design. He picks an arbitrary design constraint, in this case correctness, and argues that any language that does not provide 100% correctness is bad. He uses Rust for his examples, a language that has correctness as one of its top design goals, and contrasts it with Go, for which correctness is not that important. So of course Rust will come out on top when the only m…

What an extremely convenient template to dismiss any nuanced argument against "worse is better". You even get to question my credentials a couple times! (I apparently pick metrics that are convenient to my argument, and fundamentally misunderstand programming language design). Even if I accept the premise that "I'm challenging Go on things it doesn't promise to deliver" (which is disingenuous to begin with — correctn…

> What an extremely convenient template to dismiss any nuanced argument against "worse is better".

Nuance is exactly what I'm arguing for, there's none in the article.

> You even get to question my credentials a couple times! (I apparently pick metrics that are convenient to my argument, and fundamentally misunderstand programming language design).

You're right, I apologize. I usually try hard to never directly address whoever I'm responding to on HN, but figured it was fine since it's the linked article itself. It's clear to me now that reasoning makes no sense, I should have taken the time to reword it.

> I can't help but notice you carefully use the word "attempt" when referring to the promises Go /does/ make.

It's an acknowledgment that there's space to discuss Go failing to adhere to its design principles. I'd love to read an article on small changes to Go that would provide immense benefits. However, I don't see much value in an one-sided rant on the less-valued principles not being valued highly.

> correctness underpins /everything/, it's not a hobby

> [...]

> you don't get to choose not to care about "correctness". If you don't, you're just pushing the problem onto someone else.

Correctness isn't binary. It's perfectly valid to trade off correctness for gains elsewehere.

The classic example is companies switching from dynamic languages like Ruby to Go/Java once they hit scaling issues. Does that mean Ruby is a bad language and the company should have used Go/Java from the start? No. Using Ruby gave them the development velocity that let them get to scale in the first place.

If you do need strong correctness guarantees, by all means stay away from Go and use Rust/Ada/etc. Just remember that it's not free, something had to be traded off to achieve it.

Post reply on HN