Comment by blixt

Comment by blixt 2 days ago

324 replies | 2 pages

I've been using Go more or less in every full-time job I've had since pre-1.0. It's simple for people on the team to pick up the basics, it generally chugs along (I'm rarely worried about updating to latest version of Go), it has most useful things built in, it compiles fast. Concurrency is tricky but if you spend some time with it, it's nice to express data flow in Go. The type system is most of the time very convenient, if sometimes a bit verbose. Just all-around a trusty tool in the belt.

But I can't help but agree with a lot of points in this article. Go was designed by some old-school folks that maybe stuck a bit too hard to their principles, losing sight of the practical conveniences. That said, it's a _feeling_ I have, and maybe Go would be much worse if it had solved all these quirks. To be fair, I see more leniency in fixing quirks in the last few years, like at some point I didn't think we'd ever see generics, or custom iterators, etc.

The points about RAM and portability seem mostly like personal grievances though. If it was better, that would be nice, of course. But the GC in Go is very unlikely to cause issues in most programs even at very large scale, and it's not that hard to debug. And Go runs on most platforms anyone could ever wish to ship their software on.

But yeah the whole error / nil situation still bothers me. I find myself wishing for Result[Ok, Err] and Optional[T] quite often.

apwell23 2 days ago

> But yeah the whole error / nil situation still bothers me. I find myself wishing for Result[Ok, Err] and Optional[T] quite often.

I got insta rejected in interview when i said this in response to interview panels question about 'thoughts about golang' .

Like they said, 'interview is over' and showed me the (virtual) door. I was stunned lol. This was during peak golang mania . Not sure what happened to rancherlabs .

  • xigoi 2 days ago

    Oh my, you sure dodged a bullet.

  • arccy 2 days ago

    They probably thought you weren't going to be a good fit for writing idiomatic Go. One of the things many people praise Go for is its standard style across codebases, if you don't like it, you're liable to try and write code that uses different patterns, which is painful for everyone involved.

  • kace91 2 days ago

    Some workplaces explicitly test cultural closeness to their philosophy of work (language, architecture, etc).

    It’s part trying to keep a common direction and part fear that dislike of their tech risks the hire not staying for long.

    I don’t agree with this approach, don’t get me wrong, but I’ve seen it done and it might explain your experience.

    • laserlight a day ago

      No need to sugarcoat it. Some places are cults and it's best to avoid them. Good for GP.

Mawr 2 days ago

> I find myself wishing for Optional[T] quite often.

Well, so long as you don't care about compatibility with the broad ecosystem, you can write a perfectly fine Optional yourself:

    type Optional[Value any] struct {
     value  Value
     exists bool
    }

    // New empty.
    func New[Value any]() Optional[Value] {}

    // New of value.
    func Of[Value any](value Value) Optional[Value] {}

    // New of pointer.
    func OfPointer[Value any](value *Value) Optional[Value] {}

    // Only general way to get the value.
    func (o Optional[Value]) Get() (Value, bool) {}

    // Get value or panic.
    func (o Optional[Value]) MustGet() Value {}

    // Get value or default.
    func (o Optional[Value]) GetOrElse(defaultValue Value) Value {}

    // JSON support.
    func (o Optional[Value]) MarshalJSON() ([]byte, error) {}
    func (o *Optional[Value]) UnmarshalJSON(data []byte) error {}

    // DB support.
    func (o *Optional[Value]) Scan(value any) error {}
    func (o Optional[Value]) Value() (driver.Value, error) {}

But you probably do care about compatibility with everyone else, so... yeah it really sucks that the Go way of dealing with optionality is slinging pointers around.
  • bccdee 2 days ago

    You can write `Optional`, sure, but you can't un-write `nil`, which is what I really want. I use `Optional<T>` in Java as much as I can, and it hasn't saved me from NullPointerException.

    • Mawr a day ago

      You're not being very precise about your exact issues. `nil` isn't anywhere as much of an issue in Go as it is in Java because not everything is a reference to an object. A struct cannot be nil, etc. In Java you can literally just `return null` instead of an `Optional<T>`, not so in Go.

      There aren't many possibilities for nil errors in Go once you eliminate the self-harm of abusing pointers to represent optionality.

  • kbolino a day ago

    There's some other issues, too.

    For JSON, you can't encode Optional[T] as nothing at all. It has to encode to something, which usually means null. But when you decode, the absence of the field means UnmarshalJSON doesn't get called at all. This typically results in the default value, which of course you would then re-encode as null. So if you round-trip your JSON, you get a materially different output than input (this matters for some other languages/libraries). Maybe the new encoding/json/v2 library fixes this, I haven't looked yet.

    Also, I would usually want Optional[T]{value:nil,exists:true} to be impossible regardless of T. But Go's type system is too limited to express this restriction, or even to express a way for a function to enforce this restriction, without resorting to reflection, and reflection has a type erasure problem making it hard to get right even then! So you'd have to write a bunch of different constructors: one for all primitive types and strings; one each for pointers, maps, and slices; three for channels (chan T, <-chan T, chan<- T); and finally one for interfaces, which has to use reflection.

    • Mawr a day ago

      For JSON I just marshall to/from:

          {
           "value": "value",
           "exists: true,
          }
      
      For nil, that's interesting. I've never ran into issues there, so I never considered it.
      • kbolino a day ago

        Ideally, I would want Optional[T] to encode the same as T when a value is present, and to encode in a configurable way when the value is absent. Admittedly, the nothing to null problem exists with *T too, and even with *T and `json:",omitempty"`, you get the opposite problem (null turns to nothing). I didn't think about that at the time, so it's really more of an issue with encoding/json rather than Optional[T] per se. However, you can't implement MarshalJSON and output nothing as far as I know.

yubblegum a day ago

> Concurrency is tricky but

You hear that Rob Pike? LOL. All those years he shat on Java, it was so irritating. (Yes schadenfreude /g)

whalesalad a day ago

The remarkable thing to me about Go is that it was created relatively recently, and the collective mindshare of our industry knew better about these sorts of issues. It would be like inventing a modern record player today with fancy new records that can't be damaged and last forever. Great... but why the fuck are we doing that? We should not be writing low level code like this with all of the boilerplate, verbosity, footguns. Build high level languages that perform like low level languages.

I shouldn't fault the creators. They did what they did, and that is all and good. I am more shocked by the way it has exploded in adoption.

Would love to see a coffeescript for golang.