Live data from Hacker News

Discussion: Reduce error handling boilerplate in Golang using '?'

github.com

51–60 of 94 posts

Re: Discussion: Reduce error handling boilerplate in Golang using '?'

#51

I vote no on this proposal. Go error handling should remain simple, like the language. These are all tools, just pick the one you like and stop trying to make them like others.

C should not care for safety, there are tools, pick the one you like....

Re: Discussion: Reduce error handling boilerplate in Golang using '?'

#52
post #38

I vote no on this proposal. Go error handling should remain simple, like the language. These are all tools, just pick the one you like and stop trying to make them like others.

By that logic, Go shouldn't have generics but they've added a lot of value to our codebase.

Go is an incomplete language masquerading as a simple one.

Re: Discussion: Reduce error handling boilerplate in Golang using '?'

#53
post #14

Unfortunately, every software project will eventually reach a point of maturity where more and more features are added simply for the sake of adding them. "The goal of this proposal is to introduce a new syntax that reduces the amount of code required to check errors in the normal case, without obscuring flow of control." The key is "check errors in the normal case". When the core principles of Go have always been si…

What is happening is that Go designers are discovering that the "academic" features of the language that predated it for decades have gotten them for a reason.

Re: Discussion: Reduce error handling boilerplate in Golang using '?'

#54
post #34

Earlier quoted context omitted.

How about this? :) { foo } catch { bar }

This is probably the one that would anger Golangers the most lol

They could even have typed error checking for different errors and an automatic return error syntax.

    { Foo }
    catch (err) {}
    catch (err2){}
    throw

Re: Discussion: Reduce error handling boilerplate in Golang using '?'

#55
If I may make a suggestion to @ianlancetaylor, I think using the ? for error checking is a fantastic idea, but I think a couple small changes would make this absolutely a game changer and even more Go-like:

To demonstrate my tweak to your idea, imagine this example code:

r, err := SomeFunction() if err != nil { return fmt.Errorf("something 1 failed: %v", err) }

r2, err := SomeFunction2() if err != nil { return fmt.Errorf("something 2 failed: %v", err) }

r3, err := SomeFunction3() if err != nil { return fmt.Errorf("something 3 failed: %v", err) }

In the current proposal it would turn into this:

r := SomeFunction() ? { return fmt.Errorf("something 1 failed: %v", err) }

r2 := SomeFunction2() ? { return fmt.Errorf("something 2 failed: %v", err) }

r3 := SomeFunction3() ? { return fmt.Errorf("something 3 failed: %v", err) }

My first suggestion is to keep `err` variables visible. It ends up being not much longer, but it is much more readable and Go-like:

r, err := SomeFunction() ? { return fmt.Errorf("something 1 failed: %v", err) }

r2, err := SomeFunction2() ? { return fmt.Errorf("something 2 failed: %v", err) }

r3, err := SomeFunction3() ? { return fmt.Errorf("something 3 failed: %v", err) }

My second suggestion is to require ? to always have a block, and also allow them to "chain" so only the last statement needs a block:

r, err := SomeFunction() ? r2, err := SomeFunction2() ? r3, err := SomeFunction3() ? { return fmt.Errorf("something 1, 2 or 3 failed: %v", err) }

As you can see this is much shorter! Having the block is always required at the end of the "chain" of question mark statements is more consistent with how `if` statements require a block currently. It also makes the `return err` flow also always visible (no return magic). It also also has a huge advantage of it being much harder to miss a question mark syntactically. as a question mark without a block would be a syntax error.

For example, this is an error:

r, err := SomeFunction() ? // And also this is an error:

r, err := SomeFunction() ? r2, err := SomeFunction2() // Thanks for listening! Curious what folks think.

Re: Discussion: Reduce error handling boilerplate in Golang using '?'

#56
I overall like it and would prefer a world where Go had this spec implemented versus did not.

Criticism:

> Within the block a new variable err is implicitly declared, possibly shadowing other variables named err

Shadowing here is strange, and I would prefer a design where it did not shadow other variables named err, but rather threw a compiler error concerning the re-declaration of a variable. That would effectively mean that you can't mix-and-match this syntax with old error-handling inside one function, because code like this would fail to compile:

    func Test() {
      user, err := GetUser("12345")
      if err != nil {
        panic(err)
      }
      EmailUser(user) ? {
        panic(err)
      }
    }
I'm fearful the shadowing will be confusing, because one might try to reference that shadowed error within the block in (rare) situations where you need to return the synthesis of two error values, and you'll need to know the trivia of: `err` is a special name, I shouldn't name that shadowed variable `err`, let me name it `err2`. Granted: throwing a compiler error would also disallow this and force you to name the first variable `err2`; but at least the compiler is telling you the problem, rather than relying on your knowledge of new trivia.

Re: Discussion: Reduce error handling boilerplate in Golang using '?'

#57
post #56

I overall like it and would prefer a world where Go had this spec implemented versus did not. Criticism: > Within the block a new variable err is implicitly declared, possibly shadowing other variables named err Shadowing here is strange, and I would prefer a design where it did not shadow other variables named err, but rather threw a compiler error concerning the re-declaration of a variable. That would effectively…

I don't care for this spec and probably wouldn't use it if it were implemented, but I do like your suggestion of how to handle err shadowing.

Re: Discussion: Reduce error handling boilerplate in Golang using '?'

#58
post #50

This breaks go's readability and explicit nature. No thanks. The author doesn't understand the implications of the proposal. What if the args are in a different order returned? " foo, error " or " error, *foo " ? - I've seen many permutations of this. Being explicit about error handling is actually a good thing .

For clarity: The author is Ian Lance Taylor. He's a principal engineer at Google, on the Golang team, and the 4th largest contributor to the language. The personal attack on him not understanding the implications of the proposal is a bit cringe.

I know who he is, I stand by my statement that the proposal is ill-advised.

Re: Discussion: Reduce error handling boilerplate in Golang using '?'

#59

Earlier quoted context omitted.

I appreciate verbose and explicit patterns like this, but what go lacks is the algebraic data types/enum/unions to actually make this more ergonomic and checked. I find it bizzare that go so strongly relies on this pattern, but lacks the features to make sure you actually check for errors.

Im not really following this. Only somewhat familiar with Go. The pattern we're talking about is returning errors and having to explicitly check for them, right? How does the lack of "algebraic data types/enum/unions" make this pattern un-ergonomic?

Error patterns aren't type checked in Go. So you can forget to check an error, not notice, and ship a bug. It compounds with features like zero values and pointers-as-null to make these bugs either subtle or not subtle, but discoverable only at runtime.

Re: Discussion: Reduce error handling boilerplate in Golang using '?'

#60

The biggest issue I have with this proposal is that reading the code in naïve fashion comes up with the wrong answer for me; YMMV. The proposed form-- foo ? { bar } Reads naturally to me as "If foo then bar", when it's actually "If foo's error return exists then bar". I would suggest a different operator character, because this one reads wrongly IMO. Maybe it's just because I originally come from C, where `foo ? bar…

That is exactly how go usually works with error handling though.

    func mayfail() error {
        if snafu {
            return errors.New("oops")
        } else { return nil}
    }


    err := mayfail()
    if err != nil { handle }

Same as `mayfail() ? handle : happypath` would behave with lazy evaluation.
Post reply on HN