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: spec: allow defer with labels (Go2) #20913

Closed
ghasemloo opened this issue Jul 6, 2017 · 5 comments
Closed

proposal: spec: allow defer with labels (Go2) #20913

ghasemloo opened this issue Jul 6, 2017 · 5 comments
Labels
FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Milestone

Comments

@ghasemloo
Copy link

ghasemloo commented Jul 6, 2017

Summary:
I propose allowing allowing labels for defer statements similar to break statement.

Loop:
	for {
		for {
			break Loop
		}
	}

The break statement jumps out of both loops here. I propose that we use defer with labels to have defers that get executed when we exit a block. E.g.

func f() {
	.
	.
	.
Block:
	{
		defer Block g()
	}
	.
	.
	.
}

the deferred g() will be executed not at the end of function f() but at the end of the block.

E.g. with a lock we can have something like:

Locked:
	{
		m.Lock()
		defer Locked m.Unlock()
		.
		.
		.
	}

Background:
Developers want to defer statements to end of block and not just to the end of the function.

Proposal:
Allow defer to get executed at the end of blocks using labels.

Impact:
No impact on existing code.

Discussion:
Defer is an extremely useful feature of go. However deferring to the end of a function is not always the right choice. E.g. unlocking a lock needs to happen as soon as possible and deferring to the end of the function is not a good fit.

Alternatives:

Alternative 1: inline anonymous function
The block of code can be made an anonymous function but make a block an anonymous function just to use defer seems an abuse of anonymous function and is more verbose and can hinder readability of the code.

Alternative 2: helper function
Turning the block into a helper function can make sense sometimes but there are trade-offs, e.g. whether the block makes sense as a named function and the variables in the block will be passed to the function explicitly.

@gopherbot gopherbot added this to the Proposal milestone Jul 6, 2017
@velovix
Copy link

velovix commented Jul 11, 2017

An existing solution to the problem is to leverage anonymous functions.

func f() {
    // Some work
    func() {
        lock.Lock()
        defer lock.Unlock()
        // Some more work
    }()
    // Even more work
}

I know it's not the most beautiful syntax, but I think I prefer it aesthetically over this solution.

@ghasemloo
Copy link
Author

ghasemloo commented Jul 11, 2017

yes, this is alternative 1 in the proposal.

@velovix
Copy link

velovix commented Jul 11, 2017

Apologies, I should have read more closely.

@ghasemloo
Copy link
Author

np :) I should have included an example.

@ghasemloo ghasemloo changed the title Proposal: allow defer with labels Proposal: allow defer with labels (Go 2) Jul 12, 2017
@bradfitz bradfitz added the v2 A language change or incompatible library change label Jul 17, 2017
@bradfitz bradfitz changed the title Proposal: allow defer with labels (Go 2) Proposal: allow defer with labels Jul 17, 2017
@rsc rsc changed the title Proposal: allow defer with labels proposal: spec: allow defer with labels Jul 17, 2017
@ghasemloo ghasemloo changed the title proposal: spec: allow defer with labels proposal: spec: allow defer with labels (Go2) Jul 23, 2017
@ianlancetaylor
Copy link
Contributor

As you say, you can just use a function literal. This doesn't add any new functionality to the language. It doesn't rise to the level of something that needs to be in the language. Better to keep things simple.

@golang golang locked and limited conversation to collaborators Feb 27, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

5 participants