News for hackers. Stuff that matters.
Re:Lies we tell ourselves to keep using Golang by HL33tibCe7 on Friday April 29, 2022 @11:12AM (#31206171)
The author writes well and makes compelling points. His "I want to get off Mr Golang's Wild Ride" post is good too.

But I don't find myself agreeing with his position, which is "you shouldn't use Go for production services" (he explicitly says this in one of his Go posts, I forget which one and don't have time to look right now).

The better alternative to Go is Rust. Okay, sure, I'm willing to admit that in the examples presented, Rust handles things better. But Rust isn't a panacea. Rust is complicated and hard, and often it's not worth taking on that burden just to theoretically handle cases that rarely occur and even more rarely cause any problem. Programming is a means to an end, and the cost of using Rust (hiring, increased development time) is often not worth it.

The reason Go is successful is because it's easy for companies to use to solve production problems with teams of varying expertise. Its stdlib is well-featured, its ecosystem is good. There's generally one correct way of doing things. The same doesn't appear true in Rust. For example, an _incredibly_ common thing to do in production code is to make a web request. In Go, there is no need for debate, you use the stdlib. In Rust, you have to use a crate, which requires a decision to be made. Even worse is the async story, in Rust you have to decide whether to use Tokio or whatever. That burden is just not present with Go.

Btw this article should not be flagged and it's pathetic that people have flagged it.

Re:Lies we tell ourselves to keep using Golang by cytzol on Friday April 29, 2022 @12:05PM (#31206963)
> Programming is a means to an end, and the cost of using Rust (hiring, increased development time) is often not worth it.

I agree with this. I learnt Rust before Go, and using Go makes me feel like The Oatmeal piracy guy[1]:

"I'm not sure if I should use Go to write this HTTP service. I'd lose immutability tracking, I'd lose compiler-enforced thread safety, I'd lose the powerful type system, I'd lose the comprehensive error handling, I'd suffer from a million little papercuts, I'd have to use the weird date formatting system, I'd have to check nil pointers, I'd...

...oh, it's seven days later and I've already accomplished more writing networking servers and clients in Go than I ever have in years with Rust."

This isn't to say the points raised about Go aren't true. They are true, and if a better language were available, I wouldn't stand my ground and argue their benefits, I'd switch to it. The last comment I happened to post on this website is about how Go is insufficient without its army of linting tools [2]! Yes, I'm incredibly happy to have learnt both Go and Rust as their combination has expanded my skillset and the range of programs I'm willing to write tremendously. But if someone said to me "you should just use Rust instead of Go for your production services", I'd think the "just" was doing some incredibly heavy lifting.

An article that I'd like to see is one comparing the two languages for this niche (networking servers and clients), contrasting not just the language pitfalls but the third-party libraries necessary, the iteration speed, and the choices you'll have to make up-front. My guess is that the languages would be judged more closely together.

[1]: https://theoatmeal.com/comics/game_of_thrones [2]: https://news.ycombinator.com/item?id=30749921

Re:Lies we tell ourselves to keep using Golang by mumblemumble on Friday April 29, 2022 @04:57PM (#31210502)
I don't really use Go, I think mostly because I'm not in the target market, but this article's complaints (and some of these comments) actually got me thinking that I should take another look at it.

A long time ago, in a Haskell community chat, I saw someone dismiss Go with a pithy comment along the lines of, "Go isn't a programming language, it's a DSL for writing network services." I think I may need to re-assess that comment as actually being a really compelling elevator pitch for the language.

Armed with that perspective, I'm seeing why I wasn't terribly convinced by the article's specific complaints about Go. "Traditional IPC is a PITA and forces you toward talking over a socket? Well, yes, exactly. That's kind of the whole point."

Sometimes I wonder if we are all suffering unnecessarily because of our incessant demanding that all languages try to be all things to all people.

Re:Lies we tell ourselves to keep using Golang by lupire on Saturday April 30, 2022 @03:33PM (#31218576)
> Sometimes I wonder if we are all suffering unnecessarily because of our incessant demanding that all languages try to be all things to all people.

Programmers aren't. Programmers are building stuff and talking about that. Opinion bloggers are suffering for clicks.

Re:Lies we tell ourselves to keep using Golang by andai on Friday April 29, 2022 @07:00PM (#31211591)
I was struck by ThePrimeagen[0] saying that it took him 5x longer to write a game server in Rust than in Go—despite having significantly more Rust experience. They performed about the same (I think Go actually did better due to how much easier it was to get concurrency working?).

Personally I lean towards strict compilers (I suppose years of JavaScript has traumatized me), but 5x dev time is a big tradeoff! Of course this is just one data point, but it did seem worth mentioning.

[0] - https://www.youtube.com/watch?v=Z0GX2mTUtfo

Re:Lies we tell ourselves to keep using Golang by ay on Friday April 29, 2022 @07:35PM (#31211830)
My experience in writing a small side project in both (on the order of 2-3 KLOC) was that the time to a working project is significantly shorter with golang. The time to the correctly working project was about the same between the two.

Golang gets out of the way in me doing what I want.

Rust actively resists me doing things I will later regret.

Also, unexpectedly, I have gotten some positive comments on my C coding style after I coded some Rust.

All of this is completely anecdotal and personal experience, of course.

Re:Lies we tell ourselves to keep using Golang by lupire on Saturday April 30, 2022 @03:36PM (#31218603)
99% of people don't need "correctly" working projects.

Trillion dollar companies run on "incorrect" software.

Re:Lies we tell ourselves to keep using Golang by warabe on Saturday April 30, 2022 @06:40PM (#31220148)
Then, it's time to move on.

It is impossible to run "correct" software, but we can do better, maybe?

Re:Lies we tell ourselves to keep using Golang by Thaxll on Friday April 29, 2022 @01:46PM (#31208452)
The problem with:

"I'm not sure if I should use Go to write this HTTP service. I'd lose immutability tracking, I'd lose compiler-enforced thread safety, I'd lose the powerful type system, I'd lose the comprehensive error handling, I'd suffer from a million little papercuts, I'd have to use the weird date formatting system, I'd have to check nil pointers, I'd...

None of the modern language do it beside Rust so every language are then bad?

Re:Lies we tell ourselves to keep using Golang by mumblemumble on Friday April 29, 2022 @05:06PM (#31210593)
I think the quote marks were there to indicate that this was walking through a hypothetical thought process that someone might go through. (It proceeds on to the next line after that, where you see the closing quote mark.) The gist of the whole thing was basically to say, "Don't make the perfect the enemy of the good."
Re:Lies we tell ourselves to keep using Golang by cytzol on Friday April 29, 2022 @01:52PM (#31208537)
Sorry, I don't get what you mean. Could you elaborate or re-phrase?
Re:Lies we tell ourselves to keep using Golang by Thaxll on Friday April 29, 2022 @02:03PM (#31208661)
None of the modern and popular language have immutability, compiler enforced thread safety, powerful type ( debatable ), same for nil...

Java / C# / Python / Ruby so they fall in the same bucket as Go I assume?

Re:Lies we tell ourselves to keep using Golang by dylanowen on Friday April 29, 2022 @10:18PM (#31212777)
Java has immutability and more powerful types than go. Also considering how easy it is to intermix jvm languages you could add in scala or kotlin for truly powerful type systems without null.
Re:Lies we tell ourselves to keep using Golang by mumblemumble on Friday April 29, 2022 @11:23PM (#31213077)
I've grown a little disgruntled by the hype surrounding Scala's and Kotlin's null handling.

For starters "without null" is a myth. They both have null. They have to; there is no other practical option. The JDK uses null all over the place, so you need to have null in order to talk to the JDK.

Now, they do still have mechanism to make null easier to handle. And they're both pretty impressive designs. (Especially Kotlin's, though I haven't tried Scala 3 yet so maybe I'm missing something wonderful there. Aesthetically, I just prefer "we're going to openly acknowledge it and tame it as much as we can" over "we're going to try to sweep it under the carpet.") But there's a sort of Amdahl's Law analogue hiding in that situation: the upper bound on how much practical null safety you can achieve is constrained by how much you can avoid relying on modules that were written in Java. And I know that's basically true of languages like Haskell, too, because you often have to rely on at least a little bit of code that was written in languages like C. But it doesn't preoccupy me the same way it does in Scala or Kotlin, where interacting directly with Java code is a much more everyday kind of affair.

Re:Lies we tell ourselves to keep using Golang by ohgodplsno on Saturday April 30, 2022 @11:42AM (#31216874)
Kotlin is quite explicit about nulls.

Kotlin code requires you to use Type? if the value can ever be null.

Java code that is annotated by @Nullable/@NonNull will automatically map to Type?/Type (and it is up of course to the developer to not fuck up their nullability promises.)

Java code that is not annotated is a Type!, and encourages you to be wary about what could happen.

The nullability story is miles better than Java.

Re:Lies we tell ourselves to keep using Golang by lupire on Saturday April 30, 2022 @03:43PM (#31218662)
If you enable nullness checks, Java is the same.
Re:Lies we tell ourselves to keep using Golang by ohgodplsno on Saturday April 30, 2022 @04:58PM (#31219279)
No such thing as nullness checks in Java. At best, your IDE is taking the annotations into account and giving you warnings. At worst, you have to run ErrorProne and have it yell at you.

Additionally, all Java code (including the one you wrote) is only optionally null checked. All Kotlin code _is_ null checked, no matter what.

Re:Lies we tell ourselves to keep using Golang by lupire on Monday May 02, 2022 @04:05PM (#31240189)
ErrorProne is part of the compiler suite.
Re:Lies we tell ourselves to keep using Golang by ohgodplsno on Tuesday May 03, 2022 @07:58AM (#31247231)
??? Absolutely not. ErrorProne is a Google project that is not integrated into javac, and merely acts as a plugin to it. To have ErrorProne running on your project, you need to:

- Know about it (first, big problem for many java shops)

- Integrate it with Gradle/Maven/Ant/yourbuildtool

- Enable the null checks because they are not enabled by default.

Compare this with "it's already in the compiler"

Re:Lies we tell ourselves to keep using Golang by the_gipsy on Saturday April 30, 2022 @08:56AM (#31215689)
Had the same experience with Scala. Oh, Option types? Cool! Wait, why am I getting NPEs??? Oh, we're using some java library, nulls galore!
Re:Lies we tell ourselves to keep using Golang by mumblemumble on Saturday April 30, 2022 @11:34AM (#31216803)
I've come to the conclusion that, for the most part, option types make no sense in object-oriented languages. There are exceptions, but they tend to fall into "proves the rule" territory. OCaml, for example.

Not just because of the null problem. It's also that option types push you toward a "conditional logic everywhere" way of doing things, because that's how you handle the options. That's all well and good and holy in a functional language, and perhaps even a procedural one. But it's the opposite of good object-oriented design.

To quote Dr. Mark Crislip, when you serve cow pie with apple pie, it does not make the cow pie better. It just makes the apple pie worse.

Re:Lies we tell ourselves to keep using Golang by lupire on Saturday April 30, 2022 @03:42PM (#31218647)
How does an OO language handle a case like "Do you want fries with that?" Without conditional logic?

BurgerWithFriesMeal subclasses BurgerMeal?

"Object oriented design", in the religious sense, is an obsolete 1980s fad that took a good idea (encapsulation of mutable state) to comical extremes.

Re:Lies we tell ourselves to keep using Golang by mumblemumble on Monday May 02, 2022 @11:35AM (#31236502)
You're sort of telling on yourself with that "in a religious sense" jab. ;)

The original idea of OO design was to strive to eliminate stateful idioms. Which is a slightly different idea than what we're used to. The state existed, but the point was that you were supposed to design your system so that objects didn't need to know - or even attempt to infer - information about other objects' state.

The whole intellectual lineage that includes pervasive use of explicit state querying and manipulation methods such as getters and setters could be characterized as a whole lot of procedural programmers collectively missing the point. It's right up there with when people over-use the State monad in Haskell, effectively doing their darnedest to Greenspun imperaive programming on top of a lazy functional language because they haven't quite internalized this new paradigm yet.

Re:Lies we tell ourselves to keep using Golang by the_gipsy on Saturday April 30, 2022 @07:55PM (#31220680)
> it's the opposite of good object-oriented design.

So what is good OO design? NPEs? Nil checks?

Re:Lies we tell ourselves to keep using Golang by mumblemumble on Monday May 02, 2022 @11:27AM (#31236370)
I have yet to encounter an OO-first language for which Optional provides any real difference from nil checks. Often, it actually makes it all worse. Layering optional types on top of a system that allows any value to be nil tends to just produce a situation where there are more conditions you have to consider if you want to code defensively. As many as four:

  - nil
  - None
  - Some(nil)
  - Some(non-nil)
As far as how to do good OO design, ideally you try to avoid explicit branching whenever possible, and instead use dynamic dispatch to decide what to do. In principle, if you've architected things well, you should generally be able to avoid conditional branching.

An ironically useful example of how this works is Smalltalk's implementation of Booleans and conditionals. Smalltalk doesn't actually have an if statement. Instead, it has a Boolean class that defines three methods: ifTrue:, ifFalse:, and ifTrue:ifFalse:. Each takes one or two blocks, which are effectively anonymous functions.

And then the implementation is that the True subclass as an ifTrue: that executes the block, an ifFalse that doesn't, and an ifTrue:ifFalse: that executes its first argument. And the False implementation does the opposite.

This isn't meant to be an example of "look, OOP doesn't need conditional branching, just use {library implementation of conditional branching}," so much as a small, self-contained example of the kinds of ways that you can achieve conditional-style logic without explicit branch statements. A more real-world example might be something like having separate NotLoggedInUser and LoggedInUser classes that behave differently in relevant situations, rather than having an isLoggedIn field to have to keep checking at every use site.

The big thing working against us on this is that most the popular OO languages - C++, Java, Python, C#, etc - come from the same approach of trying to layer object-oriented features on top of a procedural core. In my not-so-humble opinion, this has been about as successful as more recent efforts to support functional programming by pulling a mess of functional features into existing OO languages. Technically it gets you somewhere, but the resulting language is not an ergonomic pit of success.

Re:Lies we tell ourselves to keep using Golang by jdougan on Monday May 02, 2022 @07:10PM (#31242332)
Probably a better example is #at:ifAbsent:, which is a place I've seen all kinds of faffing about with default retutn valures in languages without closures/blocks.
Re:Lies we tell ourselves to keep using Golang by dylanowen on Saturday April 30, 2022 @08:33AM (#31215555)
I was pretty skeptical of this and yes I'd rather not have null at all. In practice though I've found the boundary with Java for my scala projects to be very small. This is definitely a function of what you're building but there are a lot of great scala libraries so we rarely need to reach for java.
Re:Lies we tell ourselves to keep using Golang by mumblemumble on Saturday April 30, 2022 @11:31AM (#31216766)
Yeah, that's absolutely fair, a greenfield Scala project can avoid a lot of Java nowadays.

But, at the other end of things, teams that were already using Java and want to start incorporating Scala don't have that option. And 10 year old Scala projects didn't originally have that option, and doing something about it now may be a lift on the scale of a complete rewrite.

Re:Lies we tell ourselves to keep using Golang by dylanowen on Saturday April 30, 2022 @12:01PM (#31216984)
Yeah good point. I would not enjoy adding Scala throughout an established Java project unless I could really compartmentalize it
Re:Lies we tell ourselves to keep using Golang by lupire on Saturday April 30, 2022 @03:39PM (#31218629)
Java has a library for compile-time annotations static nullness checks, so if you use that, null only comes from legacy libraries, not new code.
Re:Lies we tell ourselves to keep using Golang by aidaman on Friday April 29, 2022 @09:19PM (#31212482)
Does Javascript not exist?
Re:Lies we tell ourselves to keep using Golang by imran0 on Friday April 29, 2022 @11:08PM (#31213018)
When talking about language design, it's the first one to be kicked out.
Re:Lies we tell ourselves to keep using Golang by ianbutler on Friday April 29, 2022 @03:19PM (#31209549)
Checkout Elixir, I think it's better than GO for a lot of the use cases GO handles.
Re:Lies we tell ourselves to keep using Golang by blippage on Friday April 29, 2022 @01:54PM (#31208558)
Oh man. The fake ads on that first link had me rolling around. Have an upvote!
Re:Lies we tell ourselves to keep using Golang by EdwardDiego on Friday April 29, 2022 @07:36PM (#31211837)
Haha, your comment on the weird date formatting rings very true.
Re:Lies we tell ourselves to keep using Golang by prirun on Friday April 29, 2022 @12:19PM (#31207157)
I haven't used Go or Rust seriously, but have written some Go toy code. This part of your post struck a nerve with me. I modified it slightly, to relate to Go's error handling, for me at least:

> often it's not worth taking on that burden just to theoretically handle cases that rarely occur and even more rarely cause any problem. Programming is a means to an end, and the cost of [Edit] adding if err != nil to every line of code [/Edit] (increased development time) is often not worth it.

I basically like Go, I really want to like Go, but as a Python person who has used exceptions with good success for 13 years in HashBackup, I can't see myself adding an if test to practically every line of Python code, just to catch an exception that might occur once in a blue moon.

A lot of software is not so mission critical that lives depend on it. If that is the case, sure - add error checking to every line of code. But for a lot of software, IMO, it's too much work for too little reward. If something blows up in production in an unexpected way, sometimes that's okay. You log the problem, fix it, and it's fine.

I re-read the Go error handling page before posting, because maybe it's not as bad as I had initially thought. Nope, still looks pretty cryptic to me:

https://go.dev/blog/error-handling-and-go

Re:Lies we tell ourselves to keep using Golang by j3s on Friday April 29, 2022 @02:25PM (#31208926)
> If something blows up in production in an unexpected way, sometimes that's okay. You log the problem, fix it, and it's fine.

as the person on call for such events, it's really not fine.

would you rather handle these errors upfront during development time or unexpectedly and uncontrollably, during runtime? having been on-call in one way or another for ~10 years, i know which i'd prefer.

after having used golang in production, i will never go back to using a dynamically typed language if i can avoid it. almost 0 thought or effort is required to handle errors correctly in go, and it's still possible to ignore them (just use `_`). not that i'd recommend ever doing that.

Re:Lies we tell ourselves to keep using Golang by kaba0 on Friday April 29, 2022 @04:47PM (#31210393)
It’s a big assumption that you can even handle the error at the callsite, or that you will actually handle it correctly there, or just write some low-effort attempt because the overall picture is more important for now, but later on you won’t notice how it is not correct and it will just silently fail.

Exceptions are in my honest opinion better on every single front. Checked exceptions would be the panacea but Java’s version is not the best due to subclassing. But overall bubbling up exceptions is the correct thing to do — in most cases a problem can’t be meaningfully handled at the call site. Let’s say you want to read from a file during a HTTP request but the read fails n methods deep. There can be any number of other error occurrences and the only sane choice here would be to return some error code to the web client requesting the site. Why do you want to handle it n times instead of only at the goal?

Re:Lies we tell ourselves to keep using Golang by j3s on Friday April 29, 2022 @05:56PM (#31211027)
consider this example - one using dynamic code with exception-based handling (ruby), and one using golang's more explicit error handling:

ruby:

  begin
    res = Net::HTTP.post_form(APIURL, ...)
    puts res.body
  rescue e => e
    # do error handling
  end
go:

  response, err := http.PostForm(APIURL, url.Values{...})
  if err != nil {
    # handle PostForm error
  }
  
  defer response.Body.Close()
  body, err := ioutil.ReadAll(response.Body)
  
  if err != nil {
    # handle ReadAll error
  }
  
  fmt.Printf("%s\n", string(body))
Now, for which errors do you handle? In golang, you can see clearly where errors may occur. In Ruby, it's unclear whether HTTP.post_form is even capable of throwing errors, much less what they are. For the record, here are a few of the many types of errors that can be thrown by the ruby code. Here are a few:

  Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, ...
there's no way to tell _where_ the error will even come from - you might get a Net:: error, you might get a Timeout:: error, hell you could even get an Errno::! What most programmers wind up doing is handling no errors at all until they occur in runtime - or wrapping every single "suspicious" statement in a catch-all begin/rescue block, even when it's not needed.

In golang, each function capable of returning an error simply returns it, and you must handle it at that point in time. It is very straightforward. In my experience, it results in much more reliable code. In Ruby, you have no idea what's coming. Do you see what I mean?

Re:Lies we tell ourselves to keep using Golang by weatherlite on Sunday May 08, 2022 @08:55AM (#31303590)
> there's no way to tell _where_ the error will even come from - you might get a Net:: error, you might get a Timeout:: error, hell you could even get an Errno::! What most programmers wind up doing is handling no errors at all until they occur in runtime - or wrapping every single "suspicious" statement in a catch-all begin/rescue block, even when it's not needed.

Been programming Ruby for 8 years and have never seen anyone do that, so no... If that block of code can really throw so many different types of exceptions (usually - it can't) you can always catch StandardError.

Re:Lies we tell ourselves to keep using Golang by kaba0 on Friday April 29, 2022 @06:14PM (#31211193)
I’m not familiar with Ruby, but in java you can just specify the try-catch block’s scope as explicitly as you want.

``` try { var response = http.postForm(APIURL,) } catch (Exception e) { # handle PostForm error }

try { var body = ioutil.ReadAll(response.Body) } catch(SomeSpecificExceptionType e) { # handle specific exception differently } catch(Exception e) { # run for every other kind of error }

If a given method is defined as `void postForm(…) throws IOException` you have to handle the exception at the call site, or mark the containing call itself with a similar throws clause.

I really don’t see anything not handled by these. Also, the defer part can be done by a try-with-resources construct that will clause the resource in every case, whether exited without exception or with one.

Re:Lies we tell ourselves to keep using Golang by mumblemumble on Friday April 29, 2022 @09:05PM (#31212404)
For reliability, the absolute best discipline I've ever experienced, is "Either handle the error at (or very close to) the callsite, or crash the process." But only if you make sure that everyone on the team understands that (A) this is the only way to do it, and (B) there is no other way to do it, and (C) you will do it no other way.

I think because it sets up the right psychological incentives. Because almost any option other than those two ends up looking like, "Hmm, I don't know how to handle this, but maybe someone else will, so let's bubble it up and hope they do," in practice. It's just the way we humans are.

And that sets up an intractable moral hazard situation. It creates this middle ground where two different owners of two different parts of the code can finger-point and blame and try to pass the buck. And, knowing that (though probably only unconsciously), they won't just become sloppier about handling errors. They will become sloppier about allowing errors to happen in the first place, and doing things that make it harder to handle errors. And they won't even know they're doing it.

That's what I think of when I read your hypothetical, "Let’s say you want to read from a file during a HTTP request but the read fails n methods deep." That sounds to me like code that's been structured in a way that, on this team I was alluding to above, probably wouldn't have happened in the first place and definitely wouldn't have made it past code review. The pushback would be something along the lines of, "Why on earth are you doing both file and network I/O within a single business operation but at two very different depths in the call stack? Did you even notice what you were doing here?"

Re:Lies we tell ourselves to keep using Golang by prirun on Saturday April 30, 2022 @01:25PM (#31217566)
> For reliability, the absolute best discipline I've ever experienced, is "Either handle the error at (or very close to) the callsite, or crash the process."

Here's a counterexample from HashBackup (I'm the author):

A filesystem is being backed up. Some weird error occurs, let's say it tries to read an extended attribute and gets some goofy error that raises an exception and it's not in a try/except. That error bubbles up to the try/except for "save a file", prints the exception message, and continues by backing up the next file.

Is it more reliable to crash when reading an extended attribute, aborting the whole backup? Or is it better to just tell the user about the error, finish the backup, fail at the end of the backup with a non-zero exit code, and report it in an email?

At the time of failure, the only way I can see that the error could have been handled at the call site would be to return an empty extended attrbute. To me, that's more like the "silent but wrong" solution. And there are many of these situations for saving a single file: get the flags, read the extended attribute, read the permissions and times, figure out if it's sparse, etc. Instead of having error handling at each of these steps, they can have no error handling and just raise exceptions and the high-level "save a file" handler will do everything.

Of course, along the way there are some low-level try/except blocks around code that needs cleanups, like:

  fd = None
  try:
    fd = os.open(...)
    do some stuff
  finally:
    if fd != None:
      os.close(fd)
But you have the same thing with defers in Go.
Re:Lies we tell ourselves to keep using Golang by kaba0 on Saturday April 30, 2022 @02:09AM (#31213781)
I just gave you an example from the top of my head. Here is another more realistic one, which occurred to me during the time I wrote a toy JVM: a Java class file contains a constant pool with different kinds of types. During the loading process this pool can be references by other entities as well, but they require the necessary type. Assuming verified byte code, this will be the case, but if we care about verification as well then you will quickly get into the situation where you simply can’t handle “during the loading of this class’s nth method, one of the constant pool references were of incorrect type”. It can’t be handled at method loading (or even more nested), and panicking is not the correct behavior (you only don’t want to load the given class). So you have to manually bubble it up for no benefit.
Re:Lies we tell ourselves to keep using Golang by mumblemumble on Saturday April 30, 2022 @11:10AM (#31216622)
I could believe that, but implementing JVMs is such a very specific use case, far removed from what most programmers do day-to-day. Not just because it's a VM. Because you're implementing a pre-existing specification, so you're not at liberty to make your own design decisions around something like classloader semantics. It feels like a red herring example to me. "Here's how we should think about dealing with error conditions in 2022." "But what if I've got a spec that forces me to do it 1994-style?"
Re:Lies we tell ourselves to keep using Golang by kaba0 on Saturday April 30, 2022 @11:29AM (#31216754)
There is nothing inherent to JVMs here, it is just the all around most common error type. It simply don’t make sense to handle many type of errors at call site, because it misses the big picture and for these, return types are not a good fit.
Re:Lies we tell ourselves to keep using Golang by mumblemumble on Saturday April 30, 2022 @11:40AM (#31216855)
So, the idea is basically that of the impureim sandwich: push everything that can fail out to the periphery. If it's difficult to handle errors at the call site, it's a sign that the call site is in the wrong place.
Re:Lies we tell ourselves to keep using Golang by lanstin on Saturday April 30, 2022 @04:48PM (#31219180)
With the basic idea that you should never crash due to something outside your process call stack (whether that be disk full or network problems or bad messages or bad values in a database) and always abort immediately with an email and stack trace to yourself or equiv on internal logic errors.
Re:Lies we tell ourselves to keep using Golang by AnimalMuppet on Friday April 29, 2022 @05:00PM (#31210543)
But people write "low-effort attempts" at exception handlers all the time. So using exceptions instead of error values doesn't actually change the situation.
Re:Lies we tell ourselves to keep using Golang by kaba0 on Friday April 29, 2022 @05:57PM (#31211039)
Defaults matter. Exceptions give me the question whether I want to worry about this piece of code here, or just go on and be reminded that it is actually important at runtime with an unmissable runtime error which has exact character number for the origin of the mistake. Even Java’s checked exceptions can be just added to the method signature.

(Ab)using Result types without good syntax for dealing with the very common case of “handle it higher up” (Rust’s ? macro is ok, not perfect but it is a much better compromise) is coming from a wrong angle imo.

Re:Lies we tell ourselves to keep using Golang by layer8 on Friday April 29, 2022 @01:05PM (#31207807)
> If something blows up in production

The problem is if it doesn’t quickly blow up, but instead silently corrupts data or causes other problems down the line that are hard to backtrack to that specific missing check.

Re:Lies we tell ourselves to keep using Golang by prirun on Friday April 29, 2022 @10:04PM (#31212715)
But because exceptions bubble up the stack frame, there can be no missing checks. I'm not suggesting things be coded as:

  try:
    do something
  except Exception, err:
    pass
If a piece of code is has a try/except, then it's because there is the expectation that it might fail and certain kinds of failures can be handled. If a failure is not one of the expected failures, then do a raise and let the exception go higher up. It's either going to hit a handler in the main program or will exit to command level. In either case there's a stack trace to see where the problem occurred. Exceptions tell you exactly where things blew up, whereas the "if err return" paradigm only does that if the test at each level adds identifying information.

I've seen some Go stack traces. Talk about hard to backtrack: the ones I've seen go on and on. I understand it's because there are multple Goroutines running and each one has a stack trace, but they look pretty daunting to me.

Re:Lies we tell ourselves to keep using Golang by layer8 on Saturday April 30, 2022 @04:48PM (#31219182)
I was responding to your scenario of having to “add error checking to every line of code” due to the absence of an exception mechanism, and your assertion that “it's too much work for too little reward”. My point was that in that situation (no exception mechanism available) it’s often irresponsible to not do that work, because the possible consequences are unpredictable. I fully agree that having an exception mechanism is the way to go, so that adding error checks every other line isn’t necessary anymore.
Re:Lies we tell ourselves to keep using Golang by closeparen on Friday April 29, 2022 @04:29PM (#31210224)
>you use the stdlib

* First you construct a request, and check the error on that

* Then you "Do" the request and check the error on that

* Then you check the status code (you did check it, right?)

* Then you deserialize the response and check the error on that

* Then you close the response body (you did remember to close it, right?) and check the error on that

Actually making an HTTP request with Go stdlib is a many-stage process and it is very easy to screw up or forget one of the steps. I see it all the time. Actually I have seen outages related to people being too zealous and reporting errors related to closing the response body on otherwise successful requests.

Re:Lies we tell ourselves to keep using Golang by Cthulhu_ on Tuesday May 03, 2022 @03:35AM (#31245711)
> Actually I have seen outages related to people being too zealous and reporting errors related to closing the response body on otherwise successful requests.

I kinda get it though, because the compiler or linters will show that as a warning or error going "bruh you forgot to handle this error", and as a perfectionist one wants to get rid of all of those.

I mean IMO those should be logged anyway, if only so you get some data on how often it happens, if there's anything that can be done about it, and if it's harmless, to ignore the error - but make it explicit.

Re:Lies we tell ourselves to keep using Golang by icholy on Friday April 29, 2022 @12:23PM (#31207219)
The content is mostly ok, but the title suggests that there's some obvious alternative to Go that we should be using. If he's implying it's Rust, then he's totally disconnected from reality.
Re:Lies we tell ourselves to keep using Golang by bovermyer on Friday April 29, 2022 @01:38PM (#31208354)
It's buried in the article, but I think the suggestion is "use almost any language other than Go" rather than Rust specifically.

The takeaway - if you gloss over the ranting and look for the good bits - seems to be that you should choose a language that handles a lot of the boilerplate for you (e.g., no verbose error handling) and has FFI.

It's not a bad argument, and it's making me think about how and when I use Go. For that, at least, it's worth reading.

Re:Lies we tell ourselves to keep using Golang by wperron on Friday April 29, 2022 @05:58PM (#31211041)
It's really not, and it's even saying so explicitly in the article.
Re:Lies we tell ourselves to keep using Golang by draxil on Friday April 29, 2022 @11:47AM (#31206653)
Definitely.

Go and Rust both have strengths and weaknesses.

And I think they both have a love/hate dynamic because they make pretty strong choices in their own ways, and so people react strongly in response. Personally I'm a fan of both.

Re:Lies we tell ourselves to keep using Golang by beltsazar on Saturday April 30, 2022 @02:40AM (#31213899)
> For example, an _incredibly_ common thing to do in production code is to make a web request. In Go, there is no need for debate, you use the stdlib.

And yet, Go's HTTP client doesn't have a good default [1] because of zero values, which are argued harmful in the article.

[1]: https://medium.com/@nate510/don-t-use-go-s-default-http-clie...

Re:Lies we tell ourselves to keep using Golang by azth on Saturday April 30, 2022 @01:45AM (#31213658)
> The better alternative to Go is Rust

Nope, a better alternative is Java/C#/Kotlin/etc. Those offer sum types, async programming, while being more productive than golang, and provide superior tooling and a superior developer experience.

Re:Lies we tell ourselves to keep using Golang by weatherlite on Sunday May 08, 2022 @09:02AM (#31303628)
Why not Node? Or Typescript if you really have to have types? Or even plain old PHP/Ruby (for people that just use Go to build web backends) - doesn't Kubernetes kinda solve scaling?
Re:Lies we tell ourselves to keep using Golang by Fire-Dragon-DoL on Saturday April 30, 2022 @02:48AM (#31213936)
I agree with you, however I think it's even simpler than that: the author is comparing Go to rust, but it's not comparing it to the places where it shines, that is, where Java, ruby, js, python are used.

Now suddenly we go from a poor type system (Java) to a decent one in Go (this is my personal opinion). Or from no type system to SOME type system. On top of this, we are getting all the benefits of a compiled language.

Essentially this is looking Go as a system language, while I think of it as an application language.

Aside from that, the author is right in some ways.

Re:Lies we tell ourselves to keep using Golang by goodpoint on Saturday April 30, 2022 @09:54AM (#31216093)
> The better alternative to Go is Rust

No, the better alternative is thousands of different languages.

HN is just hype-driven as usual and can see only Go and Rust.

Re:Lies we tell ourselves to keep using Golang by weinzierl on Friday April 29, 2022 @12:27PM (#31207275)
> "Even worse is the async story, in Rust you have to decide whether to use Tokio or whatever."

I think this is going to change. I couldn't find the relevant blog post now, but I believe to remember there was an initiative to provide a standard async runtime.

Re:Lies we tell ourselves to keep using Golang by afdbcreid on Sunday May 01, 2022 @04:41AM (#31223246)
No. Rust may provide some small async runtime for tutorials etc., but it'll never provide a rich async runtime like tokio because different people have different requirements from their runtime and Rust wants to satisfy them all.

What is planned is to standardize the API: that is, provide common traits for IO, tasks, etc. so libraries can be runtime-agnostic and you can change your runtime by only touching Cargo.toml (hopefully).

Re:Lies we tell ourselves to keep using Golang by weatherlite on Sunday May 08, 2022 @08:47AM (#31303547)
> The reason Go is successful is because it's easy for companies to use to solve production problems with teams of varying expertise.

It would've never got to where it's at if it wasn't for Google, that's the most important reason why its successful.

Re:Lies we tell ourselves to keep using Golang by ParetoOptimal on Thursday May 12, 2022 @01:53PM (#31357635)
> increased development time

In my experience it is only increased initial development time.

I find that initial development time is frequently conflated with development time overall.

So obviously worse is better languages will be preferred.

Re:Lies we tell ourselves to keep using Golang by sdfgdfgbsdfg on Friday April 29, 2022 @03:33PM (#31209698)
I agree with this overall.

It seems that C is a language/compiler/toolchain combo that lets you shoot yourself in the foot, but gives you enough access to stuff to be maximially performant in a random (i.e. not specialized) use case. (C++ is in this camp too).

Rust is a language/compiler/toolchain combo that tries its best to not let you shoot yourself in the foot by presenting those footguns for you to fix up front, without giving up much of the access to stuff (C++ tried some things in this camp like destructors and smart pointers. GC is also something that's in this camp)

Golang is a language/compiler/toolchain combo that lets you shoot yourself in the foot in some circumstances, and does not give you enough access to be maximally performant in every random case, but rather it seems to posit to give you opinions that will get you really, good performance in most random cases (if you need to tune the GC, for instance, you're probably worse off, like here: https://blog.twitch.tv/en/2019/04/10/go-memory-ballast-how-i...). Meaning it's making the tradeoffs of upfront complexity vs runtime issues, and Tim Toady vs The One True Way for you, because in the general case those are the most optimized tradeoffs. I don't disagree, especially when the closed-world ecosystem is good enough to not need to reach out to external tools whether those are via cgo or in the build toolchain.

In general, I think that if you reach the point where Golangs admittedly major warts are hindering your progress you're doing better than most companies, so its succeeded in not getting in the way of progress at least until that point.

In particular since the article keeps comparing Golang to Rust, for personal projects I do like the correctness of Rust, but some things are frustrating, like async being basically unusable without Async Drop, an uncertain future for completion apis, and apis that really want HKT but can't use them (yet?). I having to make up a lot of opinions that Go makes for you adds risk and uncertainty to a project where the most likely failure modes are not, in fact, those opinions.

I'm excited for the future of Java, with Loom and Valhalla coming to address as what I see as two core problems of Java in particular and other languages in general. I'm also excited for the present of js/node.js/maybe Deno. typescript has become good enough that I also think it's a really good competitor to Golang in the "just write code" arena, especially since there's significant synergy between the front end and the back end to help with build tooling, validation logic, and programmer expertise.