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: error handling in one line #57547

Closed
alarbada opened this issue Jan 2, 2023 · 9 comments
Closed

proposal: Go 2: error handling in one line #57547

alarbada opened this issue Jan 2, 2023 · 9 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

@alarbada
Copy link

alarbada commented Jan 2, 2023

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

Novice - intermediate, 1 year of experience programming full time in go.

What other languages do you have experience with?

Mostly 5 years of js / ts, some f#, some rescript, some rust.

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

A bit harder, as it adds a small special case for the if statement syntax

Has this idea, or one like it, been proposed before?

I don't think so, haven't seen

If so, how does this proposal differ?

This doesn't radically change the language

Who does this proposal help, and why?

To all go programmers, as it halves most of error handling code

What is the proposed change?

Allow the following syntax:

user, err := db.GetUser(userId)
if err != nil: return err
user, err := db.GetUser(userId)
if err != nil:
    return err

Basically, whenever an if statement (without else if // else) is ended with the : character, the following block must be of only one statement.

What would change in the language spec?

To allow colon syntax in if statements.

Is this change backward compatible?

Yes

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

It adds another syntax to if statements. The proposal would allow the following:

user, err := db.GetUser(userId)
if err != nil: return err

if user.Name == "Manolo" {
    return errors.New("User is manolo")
} else if user.Name == "Pepito" {
    return errors.New("User is pepito")
}

// ...

Which many could argue it makes code more inconsistent.

Parsing if statements can become a bit more difficult. Consider the following example:

err1 := someErr1()
err2 := someErr1()
err3 := someErr1()

if err1 != nil:
    if err2 != nil:
        if err3 != nil {
            // some other suff going on with multiple statements ...
        }

With the proposal that would be valid go code, but starts to break the beauty of the go style consistency. That could be refactored by gofmt to add braces:

err1 := someErr1()
err2 := someErr1()
err3 := someErr1()

if err1 != nil {
    if err2 != nil {
        if err3 != nil {
            // some other suff going on ...
        }
    }
}

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

gopls and gofmt I believe

What is the compile time cost?

It should be minimal,

What is the run time cost?

Should be the same as traditional error handling.

Can you describe a possible implementation?

I'm not familiar with how go lexes and does ast stuff, but basically, if statements without else clauses can have an alternative syntax as described, allowing both a condition and a statement to be in one line.

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

No

How would the language spec change?

It would add an additional requirement to the if statement.

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

It shouldn't.

Is the goal of this change a performance improvement?

No

Does this affect error handling?

Yes

If so, how does this differ from previous error handling proposals?

It is the simplest proposal that I've seen, it involves no magic in it, the syntax addition is minimal, and should be understood by all go programmers, from beginners to advanced. The new syntax also plays along with the switch statement syntax, so it subjectively fits the whole standard.

@gopherbot gopherbot added this to the Proposal milestone Jan 2, 2023
@seankhliao seankhliao added LanguageChange v2 A language change or incompatible library change error-handling Language & library change proposals that are about error handling. labels Jan 2, 2023
@seankhliao
Copy link
Member

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

@seankhliao seankhliao added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Jan 2, 2023
@alarbada
Copy link
Author

alarbada commented Jan 2, 2023

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

Done, sorry for the inconvenience

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

I think this basically replaces {\n ... \n} with : ... . I think we need a bigger gain from a syntax change, especially a syntax change that is unlike any other syntax in the language.

More likely would be #33113.

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

@beoran
Copy link

beoran commented Jan 5, 2023

@ianlancetaylor can we please reopen #33113?

I think that just changing gofmt for err != nil checks might actually solve Go's error handling problem in a very simple and elegant way.

@ianlancetaylor
Copy link
Contributor

@beoran We are not going to implement #33113. That decision stands.

What we could perhaps consider implementing is something else. These two functions are the same sequence of tokens, formatted differently. However, gofmt will not change either of them.

func F1() {
	go func() { fmt.Println("hi") }()
}

func F2() {
	go func() {
		fmt.Println("hi")
	}()
}

We could do something similar for if statements. For example, perhaps if the if statement is written as a single line, and the entire contents of the body is a single return statement, and the return statement does not contain any expressions (such as composite literals) that themselves normally require multiple lines, and if there is no else clause, then gofmt could leave that if statement unchanged.

For example, perhaps gofmt could leave this code unchanged:

func F() error {
	if _, err := fmt.Println("hi"); err != nil { return fmt.Errorf("F: %v", err) }
	return nil
}

I'm not sure whether I like that or not, personally.

@beoran
Copy link

beoran commented Jan 5, 2023

@ianlancetaylor That sounds like a good idea, then the developers can choose themselves if they want this or not.

@ianlancetaylor
Copy link
Contributor

I filed #57645.

@beoran
Copy link

beoran commented Jan 6, 2023

@ianlancetaylor Thanks!

@ianlancetaylor
Copy link
Contributor

No change in consensus.

@ianlancetaylor ianlancetaylor closed this as not planned Won't fix, can't repro, duplicate, stale Feb 2, 2023
@golang golang locked and limited conversation to collaborators Feb 2, 2024
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