Live data from Hacker News

Twelve Years of Go

go.dev

171–180 of 244 posts

Re: Twelve Years of Go

#171
post #110
post #98

Earlier quoted context omitted.

My non-Go code is starting to look more like my Go code. One of the things Go taught me is that I was not being as careful about my errors as I should be. It can be argued that exception-based handling provides you a nice baseline default, but it makes it way to easy when doing network or system-type programming to thoughtlessly default to that, when you need to be thoughtfully defaulting to that. With sufficient car…

> One of the things Go taught me is that I was not being as careful about my errors as I should be. I identify with this so much. Especially when dealing with external things (file system, database, network) things can go wrong at nearly every step. And yeah, that means you have to check errors at every step, but it forces you to think about how you want to handle them, and what message you want to propagate when the…

Things can go wrong at every step, which means each collection of fallible steps carries with it a combinatorial explosion of successes and failures. Do 5 fallible statements in sequence and it's 5+4+3+2+1 = 15 mock expectations you need to write. This tedious enumeration exercise is the majority of the time that goes into writing Go programs, for me at least.

Re: Twelve Years of Go

#172

Earlier quoted context omitted.

If you want to write unmaintainable code in Go, it's already very easy; just use interfaces incorrectly. Go lets bad programmers write bad programs. If you have a solution to that problem, your programming language will be the one that kills all current programming languages. Generics will be similar; people will misuse them, and you'll curse their names when you have to dive in and debug it. But it will also let goo…

Everything you say compfort me in the fact this is going to be bad. Everything I read in the article about generics compfort me in the fact this is going to be bad. Example: first you agree with me "its already easy to write bad code", well you agree then its gonna be easier. Your example about io.Copy. Yeah bingo, absolutely io is the exception, the only case I know in 25 years of programming that is made tasteful w…

So in your opinion, should Go also not have generics for maps and channels (as they effectively do today), or are those also one of a kind data structures that are worthy of generics?

The designers of Go recognized that generic type parameters are necessary.. it’s just that they decided to only bestow them on a few types in the standard library instead of designing a general solution.

Re: Twelve Years of Go

#173
post #68

Earlier quoted context omitted.

Most perceived verboseness of Go comes not from the language or libraries but from the formater that does not allow to compress 3 lines of the error check down to single if err != nil { return err }

Worse, if res, err := actually_important_bits(...); err != nil { return nil, err } The actually important bits are hidden in the middle of line noise. In the "common case" where `actually_important_bits` is just a simple function call it's not necessarily as bad, but the problem is when you have ten successive instances of this and one is slightly different. It's impossible to notice the important difference at a gla…

If you're using `res`, then you aren't going to scope it to the `if` statement. That is maybe another problem, sometimes you have to do this:

    res, err := actuallyImportantBits(...)
    if err != nil { 
        return nil, fmt.Errorf("actually important bits: %w", err)
    }
And other times you have to do this:

   if err := actuallyImportantBits(...); err != nil {
       return nil, fmt.Errorf("actually important bits: %w", err)
   }
The problem here is that you really don't want "err" to leak to the outer scope, so the second case is preferable from an absolute reliability and least-surprise perspective... but you can only do that in certain arbitrary cases. I think it's a bit of a wart.

You can certainly handle "res" in an else block, or even write "err == nil" and handle it there, but that is surprsing. I would say it's simply not done, ever, but the Go codebase itself does it (src/go/parser/interface.go.ParseDir was the first example I found; but my search returned many screenfuls of candidates so there are probably more cases lurking in there).

The fact that you have a choice is not ideal, basically.

But, having actually important bits in if err := ...; err != nil {} blocks is not detrimental to readability. You will know how to read that after 5 minutes of reading any Go program.

Re: Twelve Years of Go

#175
post #110

Earlier quoted context omitted.

> One of the things Go taught me is that I was not being as careful about my errors as I should be. I identify with this so much. Especially when dealing with external things (file system, database, network) things can go wrong at nearly every step. And yeah, that means you have to check errors at every step, but it forces you to think about how you want to handle them, and what message you want to propagate when the…

Things can go wrong at every step, which means each collection of fallible steps carries with it a combinatorial explosion of successes and failures. Do 5 fallible statements in sequence and it's 5+4+3+2+1 = 15 mock expectations you need to write. This tedious enumeration exercise is the majority of the time that goes into writing Go programs, for me at least.

Most of the time, you'll return early after an error.

To get into a situation where you'd need to handle n! cases, you'd need to keep running the statements after a failure, and then collate and return all the errors at the end.

Not sure why you'd want to do that. You'd definitely need to go out of your way to do something like this, and probably start asking yourself why you're doing this pretty early on. Plus it would flat out refuse to compile in some cases where there are dependencies between the statements.

Re: Twelve Years of Go

#176

Earlier quoted context omitted.

I'm a huge go proponent, but I do think the lack of map/filter/find etc. is a big downside to the language. I know how to write for (if item == myItem...) or a for (if item > max...) but it feels like a colossal waste of time every single time I write one of these loops. Go would benefit a lot more from some basic slice manipulation tools compared to features like generics that have actually made it into the language…

I imagine they'll add map/filter/find after generics are in. It's pretty easy to define some slice types though which include those in the meantime, type Slice []string and add some functions then just use your new type for collections.

I suspect but do not know that multiple return values in a function combined with the inability to write functions against multiple return types like (T,error) will limit the usefulness of traditional iterators in Go. I'd love to be proved wrong as they'd really clean up my codebase though.

Re: Twelve Years of Go

#177
post #136

Earlier quoted context omitted.

Agreed. It still surprises me that so many other languages fail at the fundamentals (minimal learning curve, static binaries, fast builds, reproducible dependency management, great tooling, great stdlib + ecosystem, etc) and yet many devotees of those languages have positively hyperventilated about Go's error handling and type system for 12 years. Go is finally getting generics and I'm sort of cautiously excited abou…

I’m not arguing that there are languages where the state of tooling is bad to say the least, but how did Go raise the bar compared to something like Java or C#, the actual “blue-collar” languages?

> how did Go raise the bar compared to something like Java or C#, the actual “blue-collar” languages?

For me, Go being combination of being well-thought-out, opinionated and batteries included took away the futile fanboi flamewars/bike-shedding: JBoss or WebSphere? Tabs or spaces? Struts or Spring?

For these reasons and more, Go is offers a more pleasant experience when working in a team. When reading code other's wrote,I encounter fewer surprises in the logic and project structure. Go codebases are easier to grok, IMO.

Re: Twelve Years of Go

#178

Earlier quoted context omitted.

Things can go wrong at every step, which means each collection of fallible steps carries with it a combinatorial explosion of successes and failures. Do 5 fallible statements in sequence and it's 5+4+3+2+1 = 15 mock expectations you need to write. This tedious enumeration exercise is the majority of the time that goes into writing Go programs, for me at least.

Most of the time, you'll return early after an error. To get into a situation where you'd need to handle n! cases, you'd need to keep running the statements after a failure, and then collate and return all the errors at the end. Not sure why you'd want to do that. You'd definitely need to go out of your way to do something like this, and probably start asking yourself why you're doing this pretty early on. Plus it wo…

It’s + not * in that example.

Re: Twelve Years of Go

#179
post #101
post #50

Earlier quoted context omitted.

If you think there's some virtue in writing verbose and inexpressive imperative code, what does Go provide in that department that you couldn't have got from Java 1.44?

I have often thought that if you could travel back in time and make Java's interfaces work like Go, there would be no Go today. The first-order effects of that change may not seem like much, but the second-order effects of that change is profound. In Java, interfaces must temporally precede their implementations; in Go they don't have to. This turns out to be huge in practice. It turns out that huge swathes of all th…

> This turns out to be huge in practice. It turns out that huge swathes of all that boilerplate and frameworkitis that Java is so well known for are just trying to get around the consequences of that mistake, because all the interface-based structure has to be laid down in advance.

I'm a little lost by what you mean here? In my mind the only difference between a Go interface and a Java interface is Java lets you declare them in the class signature.

Re: Twelve Years of Go

#180
post #151
post #129

Earlier quoted context omitted.

I think a panic is still better than a chain of if err != nil { return err } that bubbles up and does nothing. Of course the best solution would be proper error handling but not everyone does that (and it's not always obvious what to do).

and most of the time you can't handle it anyway. I mean consider you are having a database query and it fails because the connection error'd (network split). what to do know? restart the network switches and wait? of course not in http you will just print a 5xx err and hope it comes back. in go you need to bubble up these errors to your middleware and handle it there.

At the very least, you have to log that error.
Post reply on HN