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.
Twelve Years of Go
191–200 of 244 posts
Re: Twelve Years of Go
#192Earlier 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…
res, err := ...
if err != nil {
return nil, fmt.Errorf("...: %w", err)
}
for that exact reason. This doesn't scan any worse than any other text-based code. (Page in the people selling visual programming here.)Re: Twelve Years of Go
#193Earlier quoted context omitted.
> No inheritance - no more digging through the massive world-tree of objects to find the code that actually does things. That's not 100% accurate; as a concrete example, tell me which files (to say nothing of the actual downstream types!) contain the implementations of this interface method: https://github.com/kubecost/cost-model/blob/v1.88.0/pkg/clou... (err, without using github's fancy new SourceGraph-lite integra…
> That's not 100% accurate; as a concrete example, contain the implementations of this interface method But why? I've often wanted to know what a method does in Ruby and have had to resort to .method(:x).source_location because it is so dynamic only the compiler knows once it has finished running it. I've never had to find all the places that conform to an interface in Go (a very different question) or Java, because…
That's a very idealistic perspective, and my sincere congratulations that every codebase you've worked with so far has been so great as to completely and unambiguously document every edge case and pre/post condition.
If we stick just to the cited example:
Features() string // Features are a comma separated string of node metadata that could match pricing
great ... so I'm guessing if there are no such features it returns "" then, but otherwise it ... just contains the metadata keys? key=value as CSV? It escapes any "," found in the values with \\, does it? What's an example? Well, normally I'd go look at the implementations but in this awesome world of fully specified godoc I guess I shouldn't worry myself with such detailsI'm almost sorry I replied to this, because we are clearly living in such different universes, but I am actually genuinely interested in reading the URL of the godoc you've experienced that is so perfect that one need not ever bother with how many disparate implementations there are
Re: Twelve Years of Go
#194Earlier 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.
I have some code where I use multierrors and collect everything into one big error (I highly recommend this for "validation"-type code, you should generally return all errors not merely the first), but what code are you writing where you're running 5 statements unconditionally but need to handle nearly-arbitrary combinations of them failing, and multierrors aren't what you need?
Re: Twelve Years of Go
#195Earlier quoted context omitted.
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.
Re: Twelve Years of Go
#196Whats the flagship application thats written in Go? Or the application that we're most likely to have used?
1Password is also a heavy golang user, as a more silent entry into that race
Re: Twelve Years of Go
#19712 years and still no proper error handling. World stars. ;) Seriously, the error handling is a big problem with Go. Not the way it works, the way it effects how people do control flow in general.
This.
Most people are used to thinking in terms of try/catch. Programs exiting on exceptions. This is just one of those things like Garbage Collection. Its one of those things a modern programming language should do.
The example is a bit like using automatic transmission cars. As much you can sing praises of a manual transmission cars(manual control, mileage etc) its just everyday programming is like driving in roads with heavy traffic, and whatever perceived poetic beauty a manual task could offer, the automated task works better if you have to do this for hours everyday.
In many ways a language without try/catch semantics these days is dead on arrival for most shops.
Re: Twelve Years of Go
#198Earlier quoted context omitted.
> if err != nil { return err } I'm far from a Go expert, but I feel like this line is a bit pointless, especially if you write it a lot. At this point, why not just not handle the error, or panic?
Because when you're writing a reusable, self-contained function, you often don't know enough of the context to "handle" the error. Let's say you've got a function that reads from a file. If the file doesn't exist, what do you do? That entirely depends on the context the function is called in. If it's in a web server, you might return a 404. If it's a background task polling for some data, you might sleep for a while…
Re: Twelve Years of Go
#199Earlier quoted context omitted.
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.
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? Thats exactly the proper dichotomy. Those choices were made by great language designers, not by programmers. Generics are some type of macros, of course they are useful. In some rare, very sensible cases, where the added complexity is r…
At first I read this as "suitable for programmers who are 10x more productive than average ones". But they must be able to judge when/how to use generics.
Do you mean programming with 10x more code, or 10x more developers?
Re: Twelve Years of Go
#200Earlier 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 high scale, you want to perhaps try your query a few more times, backing off exponentially, maybe even round-robining (or more complicated load balancing) among different targets. Throwing up your hands and 5xx-ing a request that easily is not something you can afford at high scales of traffic where small outages happen _all the time_.