←back to thread

Go is still not good

(blog.habets.se)
644 points ustad | 2 comments | | HN request time: 0s | source
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 #
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 #
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 #
1. 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 #
2. TheDong ◴[] No.44986670[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".