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: reducing "if err != nil" by implicit form of it #41908

Closed
alisherfozilov opened this issue Oct 10, 2020 · 11 comments
Closed

proposal: Go 2: reducing "if err != nil" by implicit form of it #41908

alisherfozilov opened this issue Oct 10, 2020 · 11 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

@alisherfozilov
Copy link

Explicit is better than implicit, but there may be exceptions of the rule.

Briefly

Before:

		request, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
		if err != nil {
			log.Println(err)
			return
		}
		_ = request

After:

		request, err := http.NewRequest(http.MethodGet, "http://example.com", nil) {
			log.Println(err)
			return
		}
		_ = request

Proposal q&a

  • Would you consider yourself a novice, intermediate, or experienced Go programmer?
    Novice. 6 months using Go.

  • What other languages do you have experience with?
    C/C++ and just a little bit of Java, C#, Python, JS, Elixir.

  • Would this change make Go easier or harder to learn, and why?
    Insignificantly harder to learn: change introduces one simple thing to know.

  • Has this idea, or one like it, been proposed before?
    Yes, there are 1 relative (Proposal: gofmt should format single-statement error return on 1 line instead of current 3 lines. #33113), 2 relatively similar (proposal: Go 2: Use ?<variable> simplify handling of multiple-return-values #33074, proposal: Go 2: add "or err: statement" after function calls for error handling #33029), 2 very similar (proposal: Go 2: "onerr return" #32848, proposal: Go 2: improve error handling with “??” keyword for a special case #37243) proposals.

    • If so, how does this proposal differ?
      Described below in the answer on question "Does this affect error handling?".
  • Who does this proposal help, and why?
    This proposal helps every Go programmer and to every who switches to Go from another language. Why?
    It will reduce "if err != nil" code line, improves readability and developer's productivity, because no one will see "if err != nil" after every function call, no one will wasting time typing this line. Code will become clearer.
    For those switching from another language to Go, this will soften their attitude towards error handling in Go.

  • What is the proposed change?
    Introducing new syntax construction when function call.

    • Please describe as precisely as possible the change to the language.
      If after function call's curly brace there is "{" symbol on the same line, then there should automatic check happen "is the function's last value is not nil?". If yes, then the block that was opened with "{" symbol will execute. Otherwise that block will skipped.
    • What would change in the language spec?
      Nothing.
    • Please also describe the change informally, as in a class teaching Go.
      We just get rid of the explicit typing "if err != nil" after every function call (that returns an error).
  • Is this change backward compatible?
    Yes, absolutely.

  • Show example code before and after the change.
    Shown at the beginning of the proposal.

  • What is the cost of this proposal? (Every language change has a cost).
    The cost is time of implementing it.

    • How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
      Many tools. Compiler, vet, gofmt, IDEs.
    • What is the compile time cost?
      There is a insignificant compile cost i think. I can't answer exactly.
    • What is the run time cost?
      I think there is no run time cost. I can't answer exactly.
  • Can you describe a possible implementation?
    No.

  • How would the language spec change?
    One paragraph describing this change will be added.

  • Orthogonality: how does this change interact or overlap with existing features?
    The change does not conflicts or overlap existing features.

  • Is the goal of this change a performance improvement?
    The goal is increasing performance of developer: in creating and reading code.

    • If so, what quantifiable improvement should we expect?
      Reducing the number of lines of code in Go projects.
    • How would we measure it?
      By counting number of lines of code in public Go repositories.
  • Does this affect error handling?
    Yes.
    If so, how does this differ from previous error handling proposals?
    The reason, why proposal: Go 2: Use ?<variable> simplify handling of multiple-return-values #33074 and proposal: Go 2: add "or err: statement" after function calls for error handling #33029 were declined is as said in proposal: Go 2: add "or err: statement" after function calls for error handling #33029 (comment) :

... it requires a new keyword, which while not impossible, is a higher bar for a language change. It also introduces yet another assignment form ...

The reason, why #32848 was declined due to a problems with scope and introducing one more keyword.
The reason, why #37243 was declined due to a problems with ?? operator that has another meaning is C#. (and in my opinion operator ?? just does not fit the Golang language)

Current proposal does not do this. There is no new keyword, no new assignment form and no new operator. Language stay as simple as before.

  • Is this about generics?
    No.

Author's words

The only questions I have for now are:

  1. Is there any problem with this approach?
  2. Is it hard to implement technically and will it have a big impact on compile time?
  3. If this change is good enough, then we need to think about what is the function last return value should be when using such flow construction. Is it must be only error interface or any interface? Maybe it can be any type which can be nil?

In my opinion checking "if err != nil" is a clear and great error handling mechanism and it seems that nothing can really take place of it in Go. But it's a problematic to type this line literally after every function call, that return an error. Readability suffers too.
So let the compiler do the job for us. Reducing this line will have a big impact on code readability and programming experience.

@gopherbot gopherbot added this to the Proposal milestone Oct 10, 2020
@mvdan mvdan added WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. and removed WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. labels Oct 10, 2020
@davecheney
Copy link
Contributor

But it's a problematic to type this line literally after every function call, that return an error.

What is the problem, can you please elaborate? Where you see redundancy or duplication, I see clarity.

Readability suffers too.

Can you substantiate this position? It feel like you don’t like to read the error checks so they hurt your readability. I do like to read the error checks for two reason:

  1. They prove to me that the author of the code has thought about how the error from the call should be handled.
  2. They highlight the most important part of the authors error handling, the bit that happens after the != nil {, and the return statement.

@alisherfozilov
Copy link
Author

What is the problem, can you please elaborate? Where you see redundancy or duplication, I see clarity.

The problem is that code gets bigger due to ubiquitous "if err != nil" line. It is clear and it's obvious, that after function call there might an error happen.
Now if you call a function it's necessary typing two lines:

  1. function call
  2. if err != nil
    First part of problem is why someone should write 2-nd line manually? Even if IDE is helping, two lines of code is more lines than one. I'm not talking about that if code is short it's easier to read. Specifically in error handling it would be a good decision not to type boilerplate code every time you call a function.
    Another problem is readability. By this approach code takes less lines and looks clearer.

Can you substantiate this position? It feel like you don’t like to read the error checks so they hurt your readability.

This proposal does not aims to get rid of the error checks. The only thing wanted is letting compiler "type" != nil condition for us.

I do like to read the error checks for two reason:
1.They prove to me that the author of the code has thought about how the error from the call should be handled.
2.They highlight the most important part of the authors error handling, the bit that happens after the != nil {, and the return statement.

Again, this suggestion does not mean that you do not should to read error checks. Check out the proposal again, please.

  1. Yes, and with this approach the author of the code will still care about how the error should be handled. Nothing about it changes.
  2. It still stays here. But most important part of error handling now will happen in the block which is immediately followed by a function call.

@mvdan
Copy link
Member

mvdan commented Oct 11, 2020

There is no new keyword, no new assignment form and no new operator. Language stay as simple as before.

I'm sorry, but I disagree - you are changing the language in a very direct way. You can't claim that the language stays as simple as before when you're adding a new form of "if" conditionals.

@alisherfozilov
Copy link
Author

You are right. It's wrong to say that language will as simple as before. But before to check errors it was needed to know:

  1. what is interface, especially error interface
  2. how does 'if' works
  3. what is 'nil'
  4. function that returns many values
    and a few other Go's basics.

After this change it will be needed additionally to understand how this "new 'if' form after function call" works. One more thing to know. The helpful syntactic sugar if you let.

@martisch martisch changed the title proposal: Go 1: reducing "if err != nil" by implicit form of it proposal: Go 2: reducing "if err != nil" by implicit form of it Oct 12, 2020
@martisch martisch added v2 A language change or incompatible library change LanguageChange labels Oct 12, 2020
@ianlancetaylor ianlancetaylor added the error-handling Language & library change proposals that are about error handling. label Oct 12, 2020
@ianlancetaylor
Copy link
Contributor

See also #40432.

@ianlancetaylor
Copy link
Contributor

The description suggests that I can put a block after any function that returns at least one result.

Is this OK?

func F(err error) {}
func G() error { return nil }
func H() {
    F(G() { log.Fatal("G failed") })
}

@pofl
Copy link

pofl commented Oct 20, 2020

@alisherfozilov are you aware that the following is already possible in Go?

if request, err := http.NewRequest(http.MethodGet, "http://example.com", nil); err != nil {
	log.Println(err)
	return
}
_ = request

EDIT: oh wait no. request is undefined after the if block. Damn this always gets me.

@lu4p
Copy link

lu4p commented Oct 20, 2020

@alisherfozilov Does this still work for discarded error values?

request, _ := http.NewRequest(http.MethodGet, "http://example.com", nil) {
	return
}
_ = request

@ianlancetaylor
Copy link
Contributor

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

@Thor-x86
Copy link

Thor-x86 commented Nov 17, 2020

Instead of...

request, err := http.NewRequest(http.MethodGet, "http://example.com", nil) {
	log.Println(err)
	return
}

...which is minuscule advantage over...

if request, err := http.NewRequest(http.MethodGet, "http://example.com", nil); err != nil {
	log.Println(err)
	return
}

Why don't we add if-like that check if it's nil or not, then execute something if not nil, like this:

request, err := http.NewRequest(http.MethodGet, "http://example.com", nil)
catch err {
	log.Println(err)
	return
}

@ianlancetaylor
Copy link
Contributor

No change in consensus.

@golang golang locked and limited conversation to collaborators Nov 25, 2021
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

9 participants