ok-idiom for channels

2,742 views
Skip to first unread message

N. Riesco - GMail

unread,
Jul 24, 2012, 9:16:33 AM7/24/12
to golang-nuts
I was under the misconception that the ok-idiom could be used in
channels to avoid blocking on an empty channel. After reading the
language spec[1], I understand the ok-idiom blocks on an empty channels
unless the channel has been closed.

Could anybody say what are the use-cases for this choice?

Thx,

Nico
--


[1] http://golang.org/ref/spec#Receive_operator
"""
A receive expression used in an assignment or initialization of the form

x, ok = <-ch
x, ok := <-ch
var x, ok = <-ch

yields an additional result. The boolean variable ok indicates whether
the received value was sent on the channel (true) or is a zero value
returned because the channel is closed and empty (false)
"""
Message has been deleted

André Moraes

unread,
Jul 24, 2012, 9:19:12 AM7/24/12
to N. Riesco - GMail, golang-nuts
On Tue, Jul 24, 2012 at 10:16 AM, N. Riesco - GMail
<nicolas...@gmail.com> wrote:
> I was under the misconception that the ok-idiom could be used in channels to
> avoid blocking on an empty channel. After reading the language spec[1], I
> understand the ok-idiom blocks on an empty channels unless the channel has
> been closed.

If you don't want to block on empty/open channels, you can use select.

select {
case val <- ch1:
// use val
case val <- ch2:
// use val
default
// if both channels are empty, this is executed
}



--
André Moraes
http://amoraes.info

nkatsaros

unread,
Jul 24, 2012, 9:20:05 AM7/24/12
to golan...@googlegroups.com
If you want to avoid blocking on an empty channel use:

select {
  case x := <-ch:
    // do something with x
  default:

André Moraes

unread,
Jul 24, 2012, 9:40:01 AM7/24/12
to N. Riesco - GMail, golang-nuts
http://play.golang.org/p/oHXkW6a7WE

Here you can use a ok-idiom to detect a channel closed inside a select
statement.
Be aware of the diference from closing ch1 and ch2.

N. Riesco - GMail

unread,
Jul 25, 2012, 5:49:55 AM7/25/12
to golang-nuts
I'm going to try to answer my own question:

~ len(ch) > 0
can be used to determine whether a channel is ready for reading

~ len(ch) < cap(ch)
can be used to determine whether a channel is ready for writing

~ v, ok := <-ch
can be used to determine whether the channel is closed; although,
this risks blocking if the channel is empty but not closed. To avoid
blocking, one has to use the ok-idiom in combination with select (as
Andre pointed out).

I still find hard to understand how this ok-idiom can be useful without
a select because of the risk of blocking. Any more thoughts?

Nico

zeebo

unread,
Jul 25, 2012, 6:54:12 AM7/25/12
to golan...@googlegroups.com
You can't use len and cap to determine if a channel is ready for reading or writing as you create a race condition in some cases. If you have multiple goroutines performing an operation, you can't use len and cap to determine if that operation will proceed. For example, consider

if len(ch) > 0 {
   val := <-ch
}

When that if condition evaluates to true, implying there is a value ready to be received, another goroutine may have already received all the values on the channel by the time we try to receive it. Something similar happens with len(ch) < cap(ch) and multiple goroutines trying to send.

The code

v, ok := <-ch

will not block on a closed channel, as no receive on a closed channel blocks. The receive operation on a closed channel returns the zero value of the type the channel is for right away, but that poses an issue: how do we know if the value we received is just the zero value on the channel because someone sent it, or the zero value was because the channel was closed? Thats what "ok" tells us.

André Moraes

unread,
Jul 25, 2012, 7:35:28 AM7/25/12
to N. Riesco - GMail, golang-nuts
On Wed, Jul 25, 2012 at 6:49 AM, N. Riesco - GMail
<nicolas...@gmail.com> wrote:
> I'm going to try to answer my own question:

What are the problem that you are trying to solve?
A closed channel means something and a empty channel means another thing.

Closed channel: You can be sure that, starting now, this channel will
not return any value.
Empty channel: You can be sure that, until now, nobody is sending
nothing in this channel, but keep waiting and you could get some
value.

You use the ok idiom to detect if a channel is closed or not, if you
want to know if a channel is empty the select statement.

Using len/cap for channel isn't safe because a len followed by a
reading/writing isn't atomic and things could change from one call to
another (like zeebo) said.

N. Riesco - GMail

unread,
Jul 25, 2012, 7:38:37 AM7/25/12
to golan...@googlegroups.com
Thanks. Your answer has made understand why select it's necessary to
determine if a channel is ready for reading or writing.

Nico
Reply all
Reply to author
Forward
0 new messages