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: allow second argument to close as alternative to futures #23197

Closed
DeedleFake opened this issue Dec 20, 2017 · 6 comments
Closed
Labels
FrozenDueToAge LanguageChange Proposal v2 A language change or incompatible library change
Milestone

Comments

@DeedleFake
Copy link

I was reading through #17466 and I realized that future-style functionality already exists with channels via close(). The only real difference is that a closed channel always returns a zero value of its element type. Therefore, I propose adding a second, optional argument to close() which, if specified, causes receives on the channel to return the value given, rather than the zero value.

For example, the following would print 3 twice:

c := make(chan int)
close(c, 3)
println(<-c)
println(<-c)

I fiddled around with the runtime and compiler in an attempt to get it working myself as an experiment to see how viable it is. I'm not particularly familiar with a lot of the internals, but I managed to get it working in the runtime with minimal effort. I had a bit more trouble with getting the compiler to accept a second argument to close(), but I know that that's plausible as there are other built-in functions that do similar things.

Advantages

  • Doesn't break Go 1 compatibility guarantee. It would require a tweak to the internal structure of channels, but that's not something that's guaranteed to stay the same, so that should be fine.
  • Provides 1:N one-time broadcasting capability, as futures do, as well as the ability to receive the 'sent' value multiple times from the same channel. It basically makes channels act exactly like futures, without requiring any new types or standard library API.

Disadavantages

  • close() is a bit awkwardly named for this type of thing, even if it does make sense in terms of it being a channel. If this is accepted, it might be a good idea to do something a bit different for Go 2.

I'm sure there are other problems, but that's why I'm proposing it. I'd originally posted this as a comment on the previously referenced issue, but it's quite different from what was proposed there and no one responded, so I decided to make it a separate proposal.

@gopherbot gopherbot added this to the Proposal milestone Dec 20, 2017
@DeedleFake
Copy link
Author

Another potential issue that I had thought of but forgot about when writing the proposal is dealing with the reflect package's ability to close channels. The only way I can think of to implement it would be to add a second Close() method with a slightly different name to reflect.Value, which is less than ideal.

@ianlancetaylor ianlancetaylor changed the title proposal: Allow second argument to close as alternative to futures proposal: Go 2: allow second argument to close as alternative to futures Dec 21, 2017
@ianlancetaylor ianlancetaylor added the v2 A language change or incompatible library change label Dec 21, 2017
@extemporalgenome
Copy link
Contributor

This would make debugging harder, at least for a while. Today, if you see a flood of 3s coming out of a channel you wouldn't go look for a close. You can still implement futures easily enough by having a 'done' channel with companion value field (or values, as you'll usually want to support an error result).

@bcmills
Copy link
Contributor

bcmills commented Jan 3, 2018

The only way I can think of to implement it would be to add a second Close() method with a slightly different name to reflect.Value

(reflect.Value).Close is already weird, in that it's a method and not a package-level function. In contrast, the copy built-in is a function (reflect.Copy), new is a function (reflect.New), and make is a whole family of functions (reflect.MakeChan and friends).

It's not at all obvious to me why close, len, and cap are special enough to warrant being methods instead.

@nhooyr
Copy link
Contributor

nhooyr commented Feb 3, 2018

@bcmills maybe that should be another fix for Go 2.

@daskol
Copy link

daskol commented Mar 23, 2018

@DeedleFake This has really awkward sematics. It would be better either to introduce explicit future type or to implement it in the standard library. There are at least two reasons for that.

The first one is that you modify API of channel that it is actual standard. It will wonder people who work with fifos in Linux for example. This is why I think that future type is more suitable.

The second one is that your proposal brings some overhead to common communication and synchronization primitive. Also it is not quite obvious for me how it will affects GC and code generation due to counter 3. In my view there is lack of future. However, it is highly unclear how futures should be in language. So, we could implement following interface into standard lib as initial step.

type Future interface {
	Set(value interface{})
	Get() interface{}
	Wait()
}

@ianlancetaylor
Copy link
Contributor

The only advantage I see over a future implemented in a package is that this approach is compile-time-type-safe. I hope that in Go 2 we will have some form of generics which will permit writing a compile-time-type-safe future package. If we have that, this seems like an odd change to the existing channel semantics. If we don't have that, we can revisit this.

@golang golang locked and limited conversation to collaborators Apr 17, 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

8 participants