←back to thread

Go is still not good

(blog.habets.se)
644 points ustad | 8 comments | | HN request time: 1.165s | source | bottom
Show context
jact ◴[] No.44983294[source]
I worked briefly on extending an Go static site generator someone wrote for a client. The code was very clear and easy to read, but difficult to extend due to the many rough edges with the language. Simple changes required altering a lot of code in ways that were not immediately obvious. The ability to encapsulate and abstract is hindered in the name of “simplicity.” Abstraction is the primary way we achieve simple and easy to extend code. John Ousterhoust defined a complex program as one that is difficult to extend rather than necessarily being large or difficult to understand at scale. The average Go program seems to violate this principle a lot. Programs appear “simple” but extension proves difficult and fraught.

Go is a case of the emperor having no clothes. Telling people that they just don’t get it or that it’s a different way of doing things just doesn’t convince me. The only thing it has going for it is a simple dev experience.

replies(2): >>44985937 #>>44990107 #
1. morsecodist ◴[] No.44985937[source]
I find the way people talk about Go super weird. If people have criticisms people almost always respond that the language is just "fine" and people kind of shame you for wanting it. People say Go is simpler but having to write a for loop to get the list of keys of a map is not simpler.
replies(2): >>44986388 #>>44986425 #
2. TheDong ◴[] No.44986388[source]
I agree with your point, but you'll have to update your example of something go can't do

> having to write a for loop to get the list of keys of a map

We now have the stdlib "maps" package, you can do:

   keys := slices.Collect(maps.Keys(someMap))
With the wonder of generics, it's finally possible to implement that.

Now if only Go was consistent about methods vs functions, maybe then we could have "keys := someMap.Keys()" instead of it being a weird mix like `http.Request.Headers.Set("key", "value")` but `map["key"] = "value"`

Or 'close(chan x)' but 'file.Close()', etc etc.

replies(4): >>44986419 #>>44988173 #>>44989551 #>>44992608 #
3. morsecodist ◴[] No.44986419[source]
Fair I stopped using Go pre-generics so I am pretty out of date. I just remember having this conversation about generics and at the time there was a large anti-generics group. Is it a lot better with generics? I was worried that a lot of the library code was already written pre-generics.
replies(1): >>44986670 #
4. nixosbestos ◴[] No.44986425[source]
Ooh! Or remember when a bunch of people acted like they had ascended to heaven for looking down on syntax-highlighting because Rob said something about it being a distraction? Or the swarms blasting me for insisting GOPATH was a nightmare that could only be born of Google's hubris (literally at the same time that `godep` was a thing and Kubernetes was spending significant efforts just fucking dealing with GOPATH.).

Happy to not be in that community, happy to not have to write (or read) Go these days.

And frankly, most of the time I see people gushing about Go, it's for features that trivially exist in most languages that aren't C, or are entirely subjective like "it's easy" (while ignoring, you know, reality).

5. TheDong ◴[] No.44986670{3}[source]
The generics are a weak mimicry of what generics could be, almost as if to say "there we did it" without actually making the language that much more expressive.

For example, you're not allowed to write the following:

    type Option[T any] struct { t *T }

    func (o *Option[T]) Map[U any](f func(T) U) *Option[U] { ... }
That fails because methods can't have type parameters, only structs and functions. It hurts the ergonomics of generics quite a bit.

And, as you rightly point out, the stdlib is largely pre-generics, so now there's a bunch of duplicate functions, like "strings.Sort" and "slices.Sort", "atomic.Pointer" and "atomic.Value", quite possible a sync/v2 soon https://github.com/golang/go/issues/71076, etc.

The old non-generic versions also aren't deprecated typically, so they're just there to trap people that don't know "no never use atomic.Value, always use atomic.Pointer".

6. diarrhea ◴[] No.44988173[source]
> Now if only Go was consistent about methods vs functions

This also hurts discoverability. `slices`, `maps`, `iter`, `sort` are all top-level packages you simply need to know about to work efficiently with iteration. You cannot just `items.sort().map(foo)`, guided and discoverable by auto-completion.

7. metaltyphoon ◴[] No.44989551[source]
> Now if only Go was consistent about methods vs functions

Generics can only be on function and not methods because of it's type system. So don't hold your breath and modifying this would be a breaking change.

8. lisbbb ◴[] No.44992608[source]
I haven't use Go since 2024, but I was going to say something similar--seems like I was pretty happy doing all my Functional style coding in Go. The problem for me was the client didn't want us to use it. We were given the choice between Java (ugh) and Python to build APIs. We chose Python because I cross my arms and bite my lip and refuse to write anymore Java in these days of containers as the portability. I never really liked Java, or maybe I never really like the kinds of jobs you get using Java? <-- that