
Proposal: A built-in Go error check function, try - stablemap
https://github.com/golang/proposal/blob/master/design/32437-try-builtin.md
======
lunixbochs
I implemented try() in Go five years ago with an AST preprocessor and used it
in real projects, it was pretty nice:
[https://github.com/lunixbochs/og](https://github.com/lunixbochs/og)

Here are some examples of me using it in error-check-heavy functions:
[https://github.com/lunixbochs/poxd/blob/master/tls.go#L13](https://github.com/lunixbochs/poxd/blob/master/tls.go#L13)

~~~
X6S1x6Okd1st
I wrote something similar but of lower quality about 5 years ago as well

------
kstenerud
If it were a keyword rather than a pseudo-function, I would support its
addition. Psuedo-functions should not be allowed into the language, as they
tend to have side effects that you wouldn't expect from a function call (such
as returning from caller to grandparent).

Some keyword that implies "return if error" so that you could then do:

    
    
        try v1, v2, v3 := someFunction()
    

You could even make it a little bit smart, taking advantage of the return
types of the function to automatically fill in named return values:

    
    
        func MyFunc(param int) (result int, err error) {
            result = 0
            if param > 0 {
                result = param + 10
            } else {
                try p1, p2 := GetInternalValues(param)
                result = p1 * p2
            }
            return result, err
        }
    

where "try p1, p2 := GetInternalValues(param)" is syntactic sugar for (in this
case):

    
    
        var p1, p2 int
        p1, p2, err = GetInternalValues(param)
        if err != nil {
            return result, err
        }

~~~
013a
Given that putting 'try' before the variable definitions would probably
interfere with the 'var' keyword, it makes a bit more sense to me that it
should be put after the assignment operator (something like var try v1 =
Thing() is probably lexable consistently, but it would be confusing to
remember if it goes var try v1 or try var v1, unless it supported both which
seems ish)

    
    
        v1 := try someFunction() 
    

I like that, primarily because it has echos of how the go keyword already
operates. But the important thing is that it should be disallowed anywhere
that isn't directly next to an assignment, which might be difficult. Like

    
    
        // compiler error
        fmt.Printf(try someFunction())
    

Not sure how easily that can be enforced without affecting the lexability of
the grammar or compilation speed, but in a way, it should be thought of as a
tokenized part of the _assignment_ , not the RH-expression, such that the
assignment tokens become

    
    
        =
        :=
        = try
        := try

------
umurgdk
I am strongly against this. `try` seems exactly like a function yet it is not
acting like a function at all. People wouldn't expecting calling a function
may return from the caller. And there is a reason why golang doesn't have
macros. With macros all kind of craziness would be possible, and would really
difficult to read different kind of projects' code.

~~~
gnud
Agreed - I thought this looked pretty reasonable, if a bit parenthesis-heavy,
until I saw this example:

    
    
        func printSum(a, b string) error {
            fmt.Println(
                    "result:",
                    try(strconv.Atoi(a)) + try(strconv.Atoi(b)),
            )
            return nil
        }
    

When you nest the calls to try inside another method call, like this, the
control flow really becomes obscured.

------
abvdasker
This is interesting, but I think it doesn't necessarily fit the language well.

1\. Go has very few keywords relative to other newish languages like Swift and
Kotlin. Introducing a new one should only be done if the benefits are
undeniable.

2\. It causes an early return without any use of the "return" keyword, which
feels pretty weird.

3\. It's a bit weird that err will be magically defined in a defer function if
the surrounding function includes a "try". Does err have to be declared
earlier in the function? If yes, it's strange that it seemingly never gets
assigned. If there are multiple variables of type error in the function which
one gets assigned the result of "try"?

4\. Probably most importantly it doesn't feel very explicit. In some languages
this may not be a problem, but Go is designed to be very explicit and this
seems a bit incongruous with the rest the language's style.

Maybe I'm just not understanding the proposal. I do like how concise this is.
It's nicely backwards compatible and allows existing error handling to stay
the same.

~~~
ngrilly
1\. As explained in the proposal, try is not a keyword, but a built-in
function.

2\. Returning if there is an error is the whole point of this proposal.

3\. I don't understand your point. Could you provide an example?

4\. try is explicit. There is no implicit behavior or stack unwinding.

~~~
uryga
it uses the same syntax as functions, but it doesn't behave like a function –
functions generally can't manipulate control flow like that. so calling it a
function is weird because it's closer to a language construct like `await`

~~~
ngrilly
We already have one built-in function that alters the control flow: panic. But
I agree it's a bit weird.

~~~
uryga
tbh i don't know Go too well. as i understand it, `panic` can indeed hijack
the control flow, i.e. stop it. but any function¹ can do that: just do `while
1 {}`! control flow won't return to the caller either way. so it's not that
weird after all

Ruby blocks can do non-local control flow, i.e. return from their surrounding
function, but that's what makes them _distinct_ from functions.

\---

¹ in a turing-complete language

(i'm a Haskell enthusiast, so please excuse the nitpicking :)

~~~
ngrilly
A panic can be recovered with recover(), and thus the program can continue.
While a function that does an infinite loop will halt the program and nothing
else.

------
pcwalton
It's the try! macro from Rust! Obviously I'm a big fan of this style of error
handling, and I'm happy to see it proposed for Go.

~~~
amluto
Except it’s missing the part where sum types are used, resulting in oddities
about the non-error part of the return value when the error part is set.

~~~
pcwalton
I mean, sure, but it's the best they can do while remaining compatible with
all the Go code out there.

------
alexhutcheson
It looks like it’s basically a less hacky version of what the RETURN_IF_ERROR
and ASSIGN_OR_RETURN macros[1] do in C++.

From experience, those work pretty well. That approach eliminates a lot of the
boilerplate bookkeeping code, while still making it explicitly obvious to the
reader that a given function call can fail.

This seems nice, and I would definitely use it.

[1]
[https://github.com/protocolbuffers/protobuf/blob/master/src/...](https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/stubs/status_macros.h)

------
codr7
I get that the error is still propagated "manually" behind the scene; but how
is this different from exceptions in practice once you use try everywhere
(except where you forgot and the error is dropped silently)?

Here is my proposal: add restarts [0] as a complement to manual propagation.

[0]
[https://github.com/codr7/g-fu/blob/master/v1/doc/typical_res...](https://github.com/codr7/g-fu/blob/master/v1/doc/typical_restarts.md)

~~~
arcticbull
Exceptions are the opposite of a goto statement, basically a 'comes-from'
statement. They violate the principal of least surprise in every way possible
-- you may have no idea what type is being sent your way, where from or what
to meaningfully do about it as a result. They often result in memory leaks in
languages like C++ due to lack of destructor invocation.

try() errors can only propagate to the caller. As such, stack unwinding is
clear, no memory issues arise, performance is good and locality of error is
preserved. Surprise is minimized.

While it may look similar, it's pretty markedly different in important ways.

~~~
jacques_chester
> _you may have no idea what type is being sent your way, where from or what
> to meaningfully do about it as a result._

How is this different from (a) errors bubbling up with a pile of concatenated
strings as the only type information or (b) errors _not_ bubbling up because
someone decided _they_ would never make a mistake?

The whole value of exceptions, to me, is consistency. The error is guaranteed
to propagate in a consistent way up the stack. Static type analysis has a
fighting chance of predicting what could _ever_ propagate up the stack,
whether checked or unchecked.

Trying to work out out what `err` might be in various situations is an
exercise in forensic grepping. Trying to react intelligently and reliably to
different types of error is an exercise in hoping nobody changes the error
string.

~~~
codr7
There's no need to unwind the stack to get what you want.

Restarts [0] evaluate the error handler in the throwing scope/environment and
the only way out of there is invoking a predefined restart or aborting the
program.

[0]
[https://github.com/codr7/g-fu/blob/master/v1/doc/typical_res...](https://github.com/codr7/g-fu/blob/master/v1/doc/typical_restarts.md)

~~~
jacques_chester
I'm aware of, but have never used, the CL conditions/restarts mechanism. It
seems amazing but I wonder if it would manage to seem foreign to everyone in
one of these discussions.

------
hliyan
So basically they're proposing:

    
    
      f, err := os.Open(filename)
      if err != nil {
        return …, err  // zero values for other results, if any
      }
    

can be simplified to

    
    
      f := try(os.Open(filename))
    

This makes a lot of sense, but I'm of two minds. On one hand, it makes things
much cleaner. On the other hand, it _might_ be a first step onto a slippery
slope that ends with exceptions.

A lot of others chiming in with different ideas on the original ticket:
[https://github.com/golang/go/issues/32437](https://github.com/golang/go/issues/32437)

~~~
jerf
After chewing on this for a while, I've come to the conclusion that the thing
exceptions does wrong (or if that is too controversial, substitute "most
dangerously") is that it disconnects handling the error from the scope that
generated it. It's the way exceptions so easily fly up the stack into code
that can't understand them because it is too distant in context that is the
problem. Neither this proposal, nor any other I saw, would change that. I
wouldn't even call this "a step in the direction of exceptions"; it's a
neutral move. Everything is still occurring within the same scope, it's just
getting spelled differently.

Interestingly, this means that while pervasive use of "if err != nil { return
err }" is technically very similar to exceptions when used everywhere, it can
still have a different semantic meaning to a human reading the source.

~~~
captncraig
Every time I switch back to exception languages, I get this tendency to
"assume everything succeeds all the time, and handle it at the very top level
in case any part of it fails". I do not think about what can go wrong at each
level nearly as much as I do when I am required to use `if err != nil` soup.

~~~
nprateem
Exactly. And in most cases I don't care. Can't open that file? That's a fatal
error. Can't connect to the DB? That's a fatal error. Some file system
operation failed? That's a fatal error.

In the majority of applications it's normally pretty obvious which errors
you're likely to care about (the user already exists, etc.) vs the rest that
you just handle at the top level. The trouble with go's error handling is it
makes you care about everything, which is just a waste of time and effort
because the majority of errors will be fatal anyway.

~~~
dickeytk
I completely agree. I love that go is _able_ to treat errors just like return
values but most of the time I don't need to work with them like that. I want
to assume the happy path and not have all the `if err != nil` noise.

------
bsaul
I used to be a bit skeptical on the slow pace at which go decided to add new
feature, and the insane care they took to have orthogonal features, but after
seing the recent swift language evolution ( with google team pulling it toward
dynamic features, and now apple adding weird and clumsy DSL support) i must
say i’m now completely supporting their choice. taking a year before settling
on a less ambitious but more orthogonal and minimalist feature is a sign of
wisdom.

it is amazing the speed at which a language can go from something elegant to a
mess.

------
cpuguy83
Error handling is, to me, the most important thing when writing any code.

Promoting "if err != nil { return }" even more by giving it a keyword seems
like a dangerous road to walk down.

Are we proposing solutions to make developers not have to type "if err != nil"
or are we looking at how we can help developers handle errors better and be
more productive?

I honestly don't have anything to offer as far as ideas for changes to the
language, but I really hope we think through the long-term ramifications of
these changes.

~~~
jchw
I think the way Go error handling works is fantastic, and one of the few
problems it has is repetition. There’s C++ macros for various environments
that let you do the assign-or-propagate-error stuff with a bit less
repetition, but I dislike them because they feel opaque; people don’t often
feel the potential consequences and just use it as a way to not think about
error handling. With Go, the error handling behavior is so obvious and in your
face that it’s painful. (This doesn’t stop bad error handling hygiene, but it
has definitely helped me.)

Sadly, there’s no obvious dumb way to reduce that repetition. I would not mind
a language mechanism similar to defer, like the handle/check proposal for
example.

The most obvious issue I take with try is that it looks like a function call
but is much more magical :( and also, I dislike named returns.

~~~
marcus_holmes
I've spent the last year working on a Go system, writing Go every day.

After a couple of months, I just stopped seeing/worrying about "if err != nil
{". It has become punctuation, the Go equivalent of semicolons;

I don't even use snippets; I manually type that every time. Which is good,
because it does make me think about whether this function call can error, and
what I should do about it if it does. 90% of the time it's ("just pass it
up"), 5% of the time it's ("nothing, I don't actually care if this routine
fails") but 5% of the time it's ("right, yes, this needs to be dealt with
here").

When reading code, I just skip over it if it doesn't do anything interesting.

I understand that in English reading, we don't notice "they said"; our brains
just skip over it, and you can use "said" to open every quote and it won't
feel repetitive. That's how I've got with "if err != nil {"

so... I'm against this "try" stuff, because it feels like it's been proposed
by people who haven't worked with the language too much. I'm not against
making it more friendly for new people to learn, but this doesn't feel like
that. This just feels like "ugh, really? I have to handle _all_ the
errors?!"...which is not a reason to change it.

~~~
pjmlp
I used to write code like that during the 80 and 90's, until settling down in
languages with first class support for exceptions.

So yeah, I did it for around 20 years, and don't miss it.

~~~
jchw
I don’t like exceptions at all. They do not make it obvious what is going on,
I never am completely sure if I’m handling them right. When I want to throw an
exception I’m often unsure which would be right, and sometimes your API can
have multiple reasons to throw the same exception.

Go error handling is not like that. But I can sure as hell say fairly that Go
error handling is likely also not similar to what you did for 20 years in the
80s and 90s either. Rob Pike and friends surely knew a lot about what
programming was like at that time. I, being relatively a youngster, don’t
first hand, but I can tell you my experiences with C++, PHP, Python have not
been nearly as good as Go with error handling.

For one thing, C++ has no rigid standard for how to handle errors. Some people
use exceptions, some used error methods on classes (including the standard
library,) some used special integer or enumeration values (...including the
standard library,) and some had libraries and frameworks have their own magic
error handling mechanisms. This cognitive overhead was horrible. C wasn’t much
better; atoi is a case study in why error handling in C sucks. Libraries that
tried to standardize it, like SDL, were bearable if it was all you used, but
it probably wasn’t, and some APIs, like Win32, made it even worse. (And I
suppose it is worth at least mentioning setjmp/longjmp error handling. I don’t
think it’s necessary to comment on why it’s not good.)

Python exception handling is admittedly better, but its not really wonderful.
Exception handling code in Python is prone to breakage that is first detected
at runtime. If a function implementation changes, and the set of exceptions it
might throw changes, that’s an invisible API change that may cause an
unhandled exception in production. Not so great. Also, on a vaguely related
note, you can’t really do error values using multiple returns like in Go,
because Python doesn’t support multiple returns, only tuples, and refactoring
between returning values and tuples is likely to run into accidental runtime
errors (though you can paper over this issue a bit with type checking.)

PHP error handling sucks, I will withhold from elaborating.

All of the exception handling mechanisms suffer from one problem I really
don’t like: it’s another nearly invisible part of the API. It makes the wrong
thing (not handling errors) easy, and the right things (handling the
appropriate errors correctly) hard. Your dependencies have to care about your
call tree, and if it changes in refactoring it’s anyones bet what kinds of
exceptions your function might throw. You could catch all exceptions, but
because language errors like syntax errors (JavaScript) and index out of range
and property name errors (Python) can also be exceptions, you rarely want to
catch _all_ exceptions. Not to mention, your call itself would be caught, so
any exceptions caused by anything else in the try block would also be
conflated.

Go does some things that are mostly not new, but haven’t all been packaged
together this way before exactly:

\- Custom errors via implicit interfaces, allowing easy, arbitrary data to be
passed through errors while maintaining full control of error messages

\- Deep separation of programming errors and operational errors tend to be
passed as error values. Programming errors, like indices being out of bound or
misusing an API, typically results in a panic, whereas operational errors.
Very seldom do you actually care _what_ the error is, but when you do you can
inspect the error as any other value, because it is just any other value.

\- Ecosystem-wide standards for how to pass errors. It’s almost 100% universal
that errors are passed at the end of the return list. This makes it easy to
parse for humans and easy to lint for machines. Linters can warn you about
unused error values, and if a function suddenly has an error return it’s an
API break, forcing you to fix existing code to properly handle errors.

\- Good library support for error types, including fmt.Errorf for one-off
errors that don’t need special handling, and (third party) a myriad of error
wrapping/helper libraries. They’re not needed at all, but can be quite handy.

It works a lot better imo. You have more ceremony but less guessing. You can
read a function and see almost every edge case, and when all of the functions
perform good error hygiene you no longer need to guess about what refactoring
your code will do.

I’ll take my repetition.

~~~
pjmlp
Yeah, until one realizes that most Go error handling is a mix of

\- Parsing error results inside strings

\- if .... else boilerplate

\- Underscore everywhere to silence them

\- Abuse from panic, aka exceptions in disguise

If you want error handling without exception's guesswork, there are checked
exceptions (used for the first time in CLU 1975), and result types (used for
the first in ML in 1973)

Both without the ceremony that Go shares with Algol derived languages before
exceptions were a thing.

Rob Pike and friends surely do know a lot about what programming was like at
that time, but they are also very opinionated on what they impose on others.

Just because they have a very good career, it doesn't make them always right.

I tend to think for myself and not from opinions of others.

~~~
marcus_holmes
You've read a lot of very bad Go code then, that doesn't follow any of the
established practices for it.

Your list there is almost a primer of "what not to do in Go", and is certainly
not representative of the Go code in e.g. the standard library.

I sense some frustration about the language... what happened to make you so
anti-Go?

~~~
pjmlp
You mean like this standard library code?

[https://go.googlesource.com/proposal/+/master/design/go2draf...](https://go.googlesource.com/proposal/+/master/design/go2draft-
error-inspection.md)

> I sense some frustration about the language... what happened to make you so
> anti-Go?

Go is C with GC and bounds checking, aka Limbo reborn with some Oberon-2
influence.

Already much better for our IT safety than sticking with C, still I kind of
expected Google capable of producing Swift, Rust or TypeScript level of
language design, given their pile of PhDs.

~~~
marcus_holmes
that's not standard library code? that's a link to one of the few thousand
proposals for changing Go error handling... I'm not sure what you're trying to
say here...

I think keeping Go this simple was an extremely hard thing to do for the
designers. I don't know what the intentions were for Swift or Rust, but the Go
team were always pretty straightforward that what they wanted was a safer C to
write servers in. I think we all agree that they achieved that.

------
stepforward
If there are multiples `try` inside a single function, and we are debugging
and want to know which call raises error, how can we do that?

Should `try` wraps the error and adds something more useful for debugging
purpose? (the line number probably?)

~~~
ithkuil
Yeah, that was my first thought as well. I'm using the juju/errors library
"return errors.Trace(err)", which annotates the error with the line number of
the return.

That wouldn't work in a deferred function. Perhaps the compiler could make
that possible somehow although I suspect that might conflict with the stated
goal of improving the efficiency of defer due to "try" encouraging more people
to use it.

~~~
akavel
A deferred function is called _at the line where return would happen_ , so you
can still access stack trace information required for errors.Trace(err) from
inside a deferred function. You just need to go "one frame higher". (See the
stack trace printed in:
[https://play.golang.org/p/Bpqdm8oWBF3](https://play.golang.org/p/Bpqdm8oWBF3)).

As a result, I believe juju/errors could then be extended with a new function,
to be used like this:

    
    
        func foobar(...) (..., err error) {
            defer errors.Tracify(&err)
            ...
        }
    

where:

    
    
        package juju/errors
    
        func Tracify(err *error) {
            if *err != nil {
                *err = TraceFromDefer(*err)
            }
        }

------
dickeytk
is it just me or does the word "try" seem to imply the opposite here? To me
saying "try" is like saying "attempt to run this" like we have in a try/catch
block. I feel like something like "expect" would more directly explain what
this does.

Great functionality though. I'd be very happy to see this included no matter
what it's named.

EDIT: This is answered in the FAQ section after I read further. Apparently
it's because "try" is already a keyword. I still don't like it, but I get it.

~~~
frou_dh
See also the "continue" statement in C/Go/etc for something that does the
opposite of what the word suggests.

------
jopsen
I suspect the downside is that it'll promote blind propagation of errors.

In rust that's fine because the type system will document what error types can
be returned.

In golang, it important that every error type that can be returned is manually
documented. Otherwise, it's better to just panic, since nobody can handle
unknown errors anyways..

Or am I missing something?

~~~
xvector
Not really. You can just check if “err != nil” and switch control flow on
this.

~~~
jopsen
I always worry about state and side effects after handling an error like
that..

------
marcrosoft
Please for the love of god no.

Go is awesome for its simplicity. Errors should not be abstracted out of
handling convenience. Errors are just values either eliminate the need for the
error or handle it like you would any other value.

Stop trying to make go work like every other language.

~~~
axaxs
Agreed. This is the hill I'll die on. Boring error handling is what I
specifically love about Go...

~~~
mwaitjmp
Out of interest, how about the proposed check and handle changes proprosed for
v2?

Details here: [https://dev.to/deanveloper/go-2-draft-error-
handling-3loo](https://dev.to/deanveloper/go-2-draft-error-handling-3loo)

~~~
axaxs
Still not a fan. These seem like schemes for people who are annoyed by errors,
and just throw them over the wall... similar to say putting an entire python
block in a try/except.

With any sufficiently large application you start to realize how awful that
is, especially when something fails and the only log is 'EOF'.

I've learned to treat errors as first class citizens, because they are. I
always add an annotation and stack entry via wrappers before returning them.
Unless I'm missing something, that seems all but impossible with these
schemes.

------
leni536
Interestingly enough C++ has a recent proposal that converges to a similar
design from the other direction (i.e. exceptions).

[http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2018/p070...](http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r2.pdf)

It's still a lot more implicit than go's design, as it's meant to be
compatible with regular exceptions.

------
Insanity
I love Go, but error handling can become cumbersome. Though, I also think a
lot of that feeling is because at the codebase I'm working on we return too
many errors in a strange way.

We're returning pointers almost everywhere along with an error, even simple
methods that could do fine without. But the n you feel obligated to check them
instead of ignore them, just in case someone does change the implementation of
the simple function.

I feel like in some of the projects I wrote for myself, I use a lot less error
handling and then I don't mind the 'if err != nil' approach anymore.

I'm sure this `try` keyword will help deal with the pain from the codebase I'm
working on, though it doesn't adress the root of our problem :(

To give an idea, in a function that does 5 other function calls, I need to
check error returns 5 times. Every. Single. Line. That can't be the norm,
right? :P

~~~
kkarakk
Your second line is the answer - Go is opinionated, Go expects you to do
things in a certain way(a way that follows standard specs in most cases). If
you start bydoing a workaround in your architecture, you will similarly have
to start doing workarounds in your Go code and it becomes SUPER messy super
quickly.Google can afford to follow standard specs slavishly because giant
company with tons of money. Maybe you can't...

It's one of the pitfalls of using an opinionated language. I don't think
introducing something like this will work because it is also a hack that will
propagate other hacks in your code. Just return errors in a more standard
way(or stop using Golang)

------
cientifico
The interesting part for me about the current form is that it makes me think
what should be the state on the rest of the ecosystem in case an error
happens. That extra lines, as for experience, pays off quite fast.

This form puts to the background that though, and I fear I feel tempted to put
try everywhere.

~~~
grey-area
Don't do that then. This is just another tool in the toolbox, you don't have
to use it at all. I think I'd use it in about half the cases where I return an
error, in cases where I simply want to handle it one level up without further
annotation.

~~~
politician
Go is a managed language, and that management extends to how you are allowed
to write the code. There aren't simply tools in the toolbox, fmt and lint
_enforce_ programming styles.

In this community, it's accepted that if you didn't run `go fmt` on your code
before committing that someone else will do it for you. If you don't fix all
of the linter errors, you can expect contributions to be rejected.

If try is adopted, we can expect to see the linter pushing its usage
aggressively. The OP will be pressured to use it, and ultimately has no say in
whether they use it less than the linter demands and social expectations for
idiomatic usage compels.

~~~
grey-area
I see no reason for the linter to recommend it unless you are using if err !=
nil {return err} - if you are, it is functionally the same, therefore no
change and it would be recommended, which is fine IMO.

I don't really see the danger here - if you want to annotate errors properly,
do so, if you want to respond in place (with a retry for example), do so, if
you don't do either and just return the error (which is sometimes fine) yes
the linter would recommend the shorter version.

Where's the problem?

------
airencracken
Not a fan. I don't mind the boilerplate to be honest.

------
icholy
I think check/handle is much better than this.

~~~
grose
Same. I don't like how this requires you to use named parameters and defer to
add context to errors. It's way too easy to shadow err and I can see this
causing a lot of pain in the future.

------
pjmlp
Well, yet another magic function.

~~~
frou_dh
It seems so ad hoc. It's not really design when one just papers over a very
specific shortcoming.

~~~
boomlinde
I agree that overloading the semantics of function calls is ugly, but to play
the devil's advocate, does it have to be "design" in that sense if it truly
does address the shortcoming in a practically sufficient manner?

Aside from not appealing at all to my sense of esthetics, I have no qualms
about this because it does address a problem that a lot of people have
complained about in a way that I could get the idea within a couple of minutes
of reading the proposal. That said, a keyword might have been nicer.

~~~
frou_dh
I suppose the difference between a "quick fix" in a language and in a
codebase, is that the former will be crystalized forever.

Language designers seem to like to bang the drum about the ethos of
"Orthogonal Features". I know Go's have, in presentations. But that seems to
be cast off when the going gets tough. See also "Contracts" in Go generics,
which is mostly the same thing as the existing Interfaces feature, but working
around the fact that interfaces didn't have a good story for symbolic
operators. Orthogonal? Smorthogonal!

------
jy3
Looks a lot like the already proposed check/handle keywords that was met with
a lot of push back from the Go community:

[https://go.googlesource.com/proposal/+/master/design/go2draf...](https://go.googlesource.com/proposal/+/master/design/go2draft-
error-handling.md)

Doesn't look like the proposal adds anything new.

~~~
ngrilly
This new proposal is explicitly a simplification of the previous check/handle
proposal. And for the record, there was a lot push back, but also a lot of
support for the check/handle proposal. Language design is an iterative
process.

------
tapirl
A little similar to this one,
[https://gist.github.com/yaxinlx/1e013fec0e3c2469f97074dbf5d2...](https://gist.github.com/yaxinlx/1e013fec0e3c2469f97074dbf5d2e2c0),
but with more considerations for details.

------
gregwebs
I hope the custom handler part is reconsidered. It is fine to 4 panic if the
handler is nil or it returns nil.

------
ajcodez
It’s contrary to Go core values of simplicity and avoiding slow patterns
(using defer statements for error handling). It seems like a net loss and I
would expect the proposal to be rejected.

------
panpanna
Why not simply using a "?" the way kotlin and rust do?

