Feedback from Stripe developers on Go 2 draft designs

624 views
Skip to first unread message

Aditya Mukerjee

unread,
Oct 17, 2018, 6:13:20 PM10/17/18
to golang-nuts
Recently, several developers at Stripe who write Go regularly for their work met to discuss the Go 2 design drafts for error handling, error values, and generics. The goal of the meeting was not necessarily to provide a single conclusion on each of the design drafts, but rather to collect perspectives and opinions from various Go developers at Stripe to share more broadly. I took notes notes on the discussion; the raw and unfiltered notes are below, and I've put a short summary at the top.

As a preface:

* About ten people were present
* Not all Go developers at Stripe were present; this was a group of people who are particularly passionate about Go (and happened to be available)
* I attempted to take direct quotations as much as possible (even if the comments were blunt at times)


These notes do not reflect my personal opinions on the design drafts; they are a compilation of different perspectives that other people shared during the meeting, and which I am relaying. However, if you have questions about any of the points that people raised, I'm happy to elaborate to the best of my memory.


Overview

People were happy to see that check/handle was not a Java-like exception construct, which brings too much baggage from other languages. However, they found the control flow to be confusion, and were skeptical of whether there were enough workflows that benefited from the change to justify the added complexity. There was one workflow which was a notable exception: the check/handle construct would facilitate the pattern of “if there is any error of a certain type, perform cleanup actions”.


Error values were generally received positively, with the main questions being around how this would intersect with pkg/errors. There were a number of fans of pkg/errors (one person said “pkg/errors solved contextual information in error handling for me”). Since the error values draft is philosophically similar to pkg/errors, this was generally a positive piece of feedback, aside from questions about how a migration would work.


The design draft on generics generated the most confusion and the sharpest feedback. People were overall happy with the goal of being able to use complex data structures that others write, instead of reimplementing them ourselves. However, they were not sold on the use of contracts to achieve that goal. The syntax was controversial, and so were the semantics: people pointed out that it was confusing to reason about the implications of even seemingly-simple contracts (such as the Apply) example.



Raw notes

Error Handling:

  • How does the control flow look?

  • “Took me a while to get it, but it seems kind of reasonable. But it’s pretty hard to explain up front”

  • “I’m concerned that it’s hard to figure out - it’s no longer ‘going forward’ through the function, but now jumping around in strange ways”

  • “One tenet of Go has always been its readability, and you could always read top to bottom within a package. The fact that you jump around between handle blocks until one of them happens to return is strange”

  • “The canonical example in the design draft - even that one you have to read a few times to realize that it goes from a lower-defined handle block up to a previously-defined one”

  • “What happens if none of the handle blocks return? It’s not clear to me”

  • “Inner to outer, then up, then back”

  • “It’s about as difficult to explain as defer, but the intersection of both is weird”

  • “In small functions, it probably would scan better to have the if-check, rather than the check-handle”

  • “It is designed to remove boilerplate, but it introduces complexity. This was not originally something I found painful to deal with in the language. It feels like a solution without a problem”

  • “Now my snippet for expanding if err != nil will have to expand to “handle err { return err }”, but otherwise it won’t add anything for me”

  • “Is `defer check f.Close()` valid? If so, this would make a huge help for us in <name of service>”

  • “If any error of a certain type, clean everything up” - this makes that easier” (example code: https://gist.github.com/ChimeraCoder/9fdef30e84ab374b612533ae4fd06873)

  • For error handling: I really like the `check` nomenclature, rather than the other suggestion of `try`.  As a recovering Java programmer, I feel like `try` brings in too much baggage from that language family, and leads folks to start "thinking in exceptions" rather than adapting to Go's error handling concepts.



Error values:

  • “This sounds like the `failure` library in Rust [which may be a good thing, but is definitely an improvement over the status quo”

  • Look at the new errors proposal for Rust, which is considering putting the entire stacktrace on the error itself (controlled by an environment variable)

  • “pkg/errors solved contextual information in error handling for me”

  • What happens if you wrap a lot of errors with `fmt.Errorf`?



Generics:

  • “I’m +1 on having complicated data structures implemented by others so I don’t have to, but I’m not sure about the contract syntax”

  • “If I created a contract that essentially is powerful enough to say ‘this type must be higher-kinded’, how does the compiler know that that contract is undecidable?”

  • “This reeks of the situation with the alias proposals, where as soon as it was released into the wild, people discovered ways to write nonsensical aliases with it, and that’s why the final version took out the values portion (leaving only type aliases)”

  • “This feels half-baked”

  • “I’m even a Lisper, but why do we want everything to be in more parenthesized groups?”

  • “I’m in favor of stronger type systems, and Go’s type system is not particularly sound as it is. But I’m not sure contracts meaningfully moves the needle in one direction or the other in terms of making things better or worse vs. keeping things the same”

  • “The Apply() example is awkward syntax, and also really non-obvious”: https://go.googlesource.com/proposal/+/master/design/go2draft-contracts.md

Liam

unread,
Oct 17, 2018, 7:20:59 PM10/17/18
to golang-nuts
Hi, thanks for posting this!

> Is `defer check f.Close()` valid?
No, because the defer stack would run after the final handle block.

I describe handlers within the defer stack in Requirements to Consider for Go 2 Error Handling
https://gist.github.com/networkimprov/961c9caa2631ad3b95413f7d44a2c98a

If you have time, could you link this post from the feedback wikis for each draft design?

This post:

The feedback wikis are accessible here:

Thanks!

Ian Lance Taylor

unread,
Oct 17, 2018, 7:46:13 PM10/17/18
to Aditya Mukerjee, golang-nuts
Thanks for the feedback.

Please do add these notes to the wikis as discussed at
https://go.googlesource.com/proposal/+/master/design/go2draft.md .
Thanks.

Ian
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Liam

unread,
Oct 20, 2018, 1:41:03 PM10/20/18
to golang-nuts
I have linked the webpage for this thread on the error handling feedback wiki

Could someone link it on the other wikis?
Reply all
Reply to author
Forward
0 new messages