Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: Go 2: catch error handler #43777

Closed
dmitryuck opened this issue Jan 19, 2021 · 8 comments
Closed

proposal: Go 2: catch error handler #43777

dmitryuck opened this issue Jan 19, 2021 · 8 comments
Labels
error-handling Language & library change proposals that are about error handling. FrozenDueToAge LanguageChange Proposal Proposal-FinalCommentPeriod v2 A language change or incompatible library change
Milestone

Comments

@dmitryuck
Copy link

dmitryuck commented Jan 19, 2021

Would you consider yourself a novice, intermediate, or experienced Go programmer?
novice

What other languages do you have experience with?
JS, C#, Dart

Would this change make Go easier or harder to learn, and why?
I believe easier

Has this idea, or one like it, been proposed before?
some similar ideas of course were, but this different

If so, how does this proposal differ?

Who does this proposal help, and why?
help to handle errors in a more convenient way, increase performance by using less memory

What is the proposed change?
error handling

Please describe as precisely as possible the change to the language.
adding throw catch functionality
catch works like defer but only in case when some function in scope throws an exception
the scope of the catch block is function scope
it could be a set of catch blocks
catch block runs only if the code in func scope throws an error

What would change in the language spec?
adding throw, catch keywords

Please also describe the change informally, as in a class teaching Go.
if the function throws an error then the next catch block can handle it

Is this change backward compatible?
no, the old way should not conflict with this approach

Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit.
do not break

Show example code before and after the change.
before:

func SomeFunc() result, error {
  return nil, "error here"
}

func main() {
  res, err := SomeFunc()
  if err != nill {
    log.Println(err, "some error occur");
  }
}

after:

func SomeFunc() {
  throw "Error in SomeFunc"
}


func main() {
  result := SomeFunc()

  catch func(e error) {
    log.Println("some error occur");
  }
}

or:

func SomeFunc() {
  throw "Error in SomeFunc"
}

func ErrorHandler(e error) {
  log.Println(e, "some error occur");
}

func main() {
  result2 := SomeFunc()
  catch ErrorHanler
}

or:

func SomeFunc_1() {
  throw ERROR_TYPE_1
}

func SomeFunc_2() {
  throw ERROR_TYPE_2
}

func SomeFunc_3() {
  throw ERROR_TYPE_3
}

func ErrorHandler(e error) {
  switch(e) {
    case ERROR_TYPE_1: DoSomething()
    case ERROR_TYPE_2: DoSomething()
    case ERROR_TYPE_3: DoSomething()
  }

  log.Println(e, "some error occur");
}


func main() {
  result1 := SomeFunc_1()
  result2 := SomeFunc_2()
  result3 := SomeFunc_3()

  catch ErrorHanler
}

What is the cost of this proposal? (Every language change has a cost).
benefits of having this approach :

  • no return error from function,
  • no error declaration in return parameters,
  • no error variable declaration in function calls scope,
  • no code like if err != nill

How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
none

What is the compile time cost?
possible internal optimization as a new mechanism

What is the run time cost?
possible internal optimization as a new mechanism

Can you describe a possible implementation?
sure

Do you have a prototype? (This is not required.)
code above

How would the language spec change?
a bit

Orthogonality: how does this change interact or overlap with existing features?
does not conflict

Is the goal of this change a performance improvement?
performance improvements also

If so, what quantifiable improvement should we expect?
an application could use less memory

How would we measure it?
depends on implementation

Does this affect error handling?
yes

If so, how does this differ from previous error handling proposals?
because not necessary to create a new variable err every time, performance increases

Is this about generics?
nope

If so, how does this differ from the current design draft and the previous generics proposals?
don't know

@seankhliao seankhliao changed the title Proposal to errors handling proposal: Go 2: catch error handler Jan 19, 2021
@gopherbot gopherbot added this to the Proposal milestone Jan 19, 2021
@seankhliao seankhliao added error-handling Language & library change proposals that are about error handling. v2 A language change or incompatible library change WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. labels Jan 19, 2021
@seankhliao
Copy link
Member

Please fill out https://github.com/golang/proposal/blob/master/go2-language-changes.md when proposing language changes

@mdlayher
Copy link
Member

Some form of try/catch has been proposed many times in the past and none of these proposals have been accepted: https://github.com/golang/go/issues?q=is%3Aissue+is%3Aclosed+%22try%2Fcatch%22+label%3Aerror-handling+

What makes this proposal any different?

@dmitryuck
Copy link
Author

dmitryuck commented Jan 19, 2021

no returning error from function, internal mechanisms for observe, only throw operator which makes error call and catch the handler. something very similar to other languages semantically. one more thing to language core developers to notice, although such engineers better know

@seankhliao seankhliao removed the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Jan 19, 2021
@ianlancetaylor
Copy link
Contributor

What is the difference between throw and panic?

What is the difference between catch and a deferred call to recover?

@dmitryuck
Copy link
Author

dmitryuck commented Jan 20, 2021

as far as I know, panic should be used as limited as possible, especially in libraries
panic pops up until recover found, similar mechanics but only pops up in one level
can work like a defer, any thrown error catches in the block.
if there few blocks they execute one by one, to break catch execution queue use return from anyone

func SomeFunc_1() {
  throw Error(ERR_NOT_FOUND)
}

func SomeFunc_2 {
  throw Error(ERR_CONNECTION_CLOSE)
}

func main() {
  catch func(e error) {
    switch(e.Type) {
      case ERR_NOT_FOUND: DoSomething()
      case ERR_CONNECTION_CLOSE: DoSomething()
    }

    log.Println(e, "error occur in this scope")
  }

  result_1 := SomeFunc_1()
  result_2 := SomeFunc_2()
}

the function returns only useful payload, no error tails, code become clearer
this approach can also increase performance, because not necessary to create a new variable err every time
for ex. the scope has 10 such err variables so they can be handled in one catch block, performance increases
when the whole application has hundreds, avoiding that is already an optimization

so what I mean here, this is essentially a try-catch-finally behavior:
the body of the function is a try block by itself, if any error occurred then the catch block will handle it, if any defer blocks present - they will be called anyway like a finally statement

@ianlancetaylor
Copy link
Contributor

What happens if there is a throw but no catch? Is that any different from a panic with no deferred recover?

It's fine to call panic in a library as long you recover the panic. For example, look at the use of panic in https://golang.org/src/encoding/json/encode.go.

I agree that calls to panic that are not recovered should normally be avoided. If we were to add throw to the language, the same guidelines would apply to throw.

@dmitryuck
Copy link
Author

dmitryuck commented Jan 21, 2021

I think if no catch is the same when no if err != nil, but yes here is the field for discussion
that means you do not handle any error in the scope, which is obviously bad
in that example, panic means that happed something very dangerous for the further application existence and it makes sense
panic should exist alongside errors it's an axiom
panic pop up until recover found, throw catch applies on the func scope, so surfacing on one level only

or throw ia s function, catch operator:

func SomeFunc() {
  throw("Error in SomeFunc")
}

func ErrorHandler(e error) {
  log.Println(e, "some error occur");
}

func main() {
  result := SomeFunc()

  catch(e error) {
    log.Println("some error occur");
  }

  catchFunc(ErrorHandler)
}

@ianlancetaylor
Copy link
Contributor

Based on the discussion above, and the lack of support in the emoji voting, this is a likely decline. Leaving open for four weeks for final comments.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
error-handling Language & library change proposals that are about error handling. FrozenDueToAge LanguageChange Proposal Proposal-FinalCommentPeriod v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

5 participants