Live data from Hacker News

What canceled my Go context?

rednafi.com

41–50 of 70 posts

Re: What canceled my Go context?

#41
post #33

Earlier quoted context omitted.

I agree go’s error handling feels a bit clunky, though I prefer the local error handling and passing up the chain (if it were a bit more ergonomic) to exceptions, which IMO have a lot of other problems. The main problems seem to me to be boilerplate and error types being so simplistic (interface just has a method returning a string). Boilerplate definitely seems solvable and a proper error interface too. I tend to us…

In an HTTP server, top level means the handlers, is that so?

Yes I guess I do annotation in two places - initial error deep in libraries is annotated, this is passed back up to the initial handlers who log and respond and decide what to show users. Obviously that’s just a rule of thumb and doesn’t always apply.

Depends if it can be handled lower (with a retry or default data for example), if it can be it won’t be passed all the way up.

Generally though I haven’t personally found it useful to always annotate at every point in the call chain. So my default is not to annotate and if err return err.

What I like about errors instead of exceptions is they are boring and predictable and in the call signature so I wouldn’t want to lose that.

Re: What canceled my Go context?

#42
post #34

Earlier quoted context omitted.

Then it results in an absurd amount of duplication. I regularly encounter error strings like: error:something happened:error:something happened

Yes, and that is desired. Error: failed processing order: account history load failure: getUser error: context deadline exeeded

I’d find Error: failed processing order: context deadline exceeded just as useful and more concise.

Typically there is only one possible code path if you can identify both ends.

Re: What canceled my Go context?

#43
I think this post needs better examples to show case the issue, because right now the issue is not clear. Ideally you would need an example that uses the context.Cause function, see below

The contexts and errors communicate information in different directions. Errors let upstream function know what happened within the call, context lets downstream functions know what happened elsewhere in the system. As a consequence there isn't much point to cancel the context and return the error right away if there isn't anybody else listening to it.

Also, context can be chained by definition. If you need to be able to cancel the context with a cause or cancel it with a timeout, you can just make two context and use them.

Example that shows the approach as well as the specific issue raised by the post: https://go.dev/play/p/rpmqWJFQE05

Thanks for the post though! Made me think about contexts usage more

Re: What canceled my Go context?

#44

Earlier quoted context omitted.

Yes, and that is desired. Error: failed processing order: account history load failure: getUser error: context deadline exeeded

I’d find Error: failed processing order: context deadline exceeded just as useful and more concise. Typically there is only one possible code path if you can identify both ends.

Not in my experience. Usually your call chain has forks. Usually the DoThing function will internally do 3 things and any one of those three things failed and you need a different error message to disambiguate. And four methods call DoThing. The 12 error paths need 12 uniquely rendered error messages. Some people say "that is just stack traces," and they are close. It is a concise stack trace with the exact context that focuses on your code under control.

Re: What canceled my Go context?

#45

Earlier quoted context omitted.

I’d find Error: failed processing order: context deadline exceeded just as useful and more concise. Typically there is only one possible code path if you can identify both ends.

Not in my experience. Usually your call chain has forks. Usually the DoThing function will internally do 3 things and any one of those three things failed and you need a different error message to disambiguate. And four methods call DoThing. The 12 error paths need 12 uniquely rendered error messages. Some people say "that is just stack traces," and they are close. It is a concise stack trace with the exact context t…

If you have both the start of the call chain and the end of the call chain mapped you will get a different error response almost every time and it is usually more than enough, so say your chain is:

Do1:...Do10, which then DoX,DoY,DoZ and one of those last 3 failed.

Do you really need Do1 to Do10 to be annotated to know that DoY failed when called from Do1? I find:

Do1:DoZ failed for reason bar

Just as useful and a lot shorter than: Do1: failed:Do2:failed...Do9 failed:Do10:failed:DoZ failed for reason bar

It is effectively a stack trace stored in strings, why not just embed a proper stack trace to all your errors if that is what you want?

Your concern with having a stack trace of calls seems a hypothetical concern to me but perhaps we just work on different kinds of software. I think though you should allow that for some people annotating each error just isn't that useful, even if it is useful for you.

Re: What canceled my Go context?

#47
post #34

Earlier quoted context omitted.

> After a decade of writing Go I still don’t have a good rule of thumb for when I should wrap an error with more info or return it as-is. The rule of thumb is to wrap always.

Then it results in an absurd amount of duplication. I regularly encounter error strings like: error:something happened:error:something happened

After a decade of writing go, I always wrap with the function name and no other content. For instance:

do c: edit b: create a: something happened

For functions called doC, editB, createA.

It’s like a stack trace and super easy to find the codepath something took.

Re: What canceled my Go context?

#48
post #47
post #34

Earlier quoted context omitted.

Then it results in an absurd amount of duplication. I regularly encounter error strings like: error:something happened:error:something happened

After a decade of writing go, I always wrap with the function name and no other content. For instance: do c: edit b: create a: something happened For functions called doC, editB, createA. It’s like a stack trace and super easy to find the codepath something took.

I have a single wrap function that does this for all errors. The top level handler only prints the first two, but can print all if needed.

I have never had difficulty quickly finding the error given only the top two stack sites.

Any complaint about go boilerplate is flawed. The purpose and value is not in reducing code written, it is to make code easier to read and it achieves this goal better than any other language.

This value is compounding with coding agents.

Re: What canceled my Go context?

#49

It’s great that they identified this (incredibly common) pain point and introduced a way to solve it, but I can’t help being disappointed. Reading the examples I found myself thinking, “that looks like a really useful pattern, I should bookmark this so I can adopt it whenever I write code like that.” The fact that I’m considering bookmarking a blog post about complex boilerplate that I would want to use 100% of the t…

> After a decade of writing Go I still don’t have a good rule of thumb for when I should wrap an error with more info or return it as-is.

When writing your tests:

1. Ensure all error cases are identifiable to the caller — i.e. using errors.Is/errors.AsType

2. Ensure that you are not leaking the errors from another package — you might change the underlying package later, so you don't want someone to come to depend on it

As long as those are satisfied, it doesn't matter how it is implemented.

Re: What canceled my Go context?

#50
post #34

Earlier quoted context omitted.

Then it results in an absurd amount of duplication. I regularly encounter error strings like: error:something happened:error:something happened

Yes, and that is desired. Error: failed processing order: account history load failure: getUser error: context deadline exeeded

This feels like manually written stacktraces
Post reply on HN