selecting with and without default

1,046 views
Skip to first unread message

Marko Kevac

unread,
Sep 19, 2014, 4:59:39 PM9/19/14
to golan...@googlegroups.com
Here is a very simple program. With default case it prints only 0. Without it prints 0, 1, 2.
Why is that? Goroutine is always ready to send a number into channel, but main function thinks it is not?

Henrik Johansson

unread,
Sep 19, 2014, 5:06:46 PM9/19/14
to Marko Kevac, golang-nuts

Why do have that first select in the  A function?

"The default clauses in the select statements execute when no other case is ready, meaning that the selects never block"

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Caleb Spare

unread,
Sep 19, 2014, 5:09:41 PM9/19/14
to Marko Kevac, golang-nuts
It's not ready. It's up to particular scheduler timing, and in this
case, the scheduler looks like it's running all three iterations of
the for loop in main before it runs the second and third iterations of
the loop in A.

Note that because GOMAXPROCS defaults to 1, you're only going to be
running one of those loops in parallel. If I set GOMAXPROCS=2 and run
the test several times, I get varied results (sometimes 0 1, sometimes
0 1 2). But again, it's all timing-dependent. Nothing guarantees that
the A loop has a chance to reach out <- i before the main loop is
ready to receive.

-Caleb

andrey mirtchovski

unread,
Sep 19, 2014, 5:10:57 PM9/19/14
to Marko Kevac, golang-nuts
> Why is that? Goroutine is always ready to send a number into channel, but
> main function thinks it is not?

goroutine is ready to send but it hasn't actually sent anything yet:
it's blocked on sending after the first item. if the channel was
buffered it would send out all available ints until it fills it up and
then main's select{} would see a channel ready to receive from:

http://play.golang.org/p/nHjOiQzgiz

Caleb Spare

unread,
Sep 19, 2014, 5:27:14 PM9/19/14
to andrey mirtchovski, Marko Kevac, golang-nuts
> goroutine is ready to send but it hasn't actually sent anything yet:
> it's blocked on sending after the first item.

This isn't quite accurate. With unbuffered chans, if the sender is
blocked and ready to send, the receiver will get a value (and the
default case will not be taken). So what's happening here is that the
sleep gives the sender time to be ready to send the first item (0),
which is received and printed, but then the next two iterations of the
receiver both run (and take the default case) before the sender is
ready to send again.

andrey mirtchovski

unread,
Sep 19, 2014, 5:52:00 PM9/19/14
to Caleb Spare, Marko Kevac, golang-nuts
ok, another way to think about this is to remove the loop restriction,
loop forever and see how many times each branch of the select
statement is taken (i.e., how often is the other goroutine allowed to
run given a default case in main's select statement):

http://play.golang.org/p/E5TdhiXFn2 (don't run this in the playground)

run with GOMAXPROCS=1 and 2 to see how this affects scheduling of goroutines.

finally, comment out runtime.Gosched() to see how it behaves when the
default branch always "yields" (and note that even then the default
branch could be taken consecutively without a value read from the
chan).

ma...@kevac.org

unread,
Sep 20, 2014, 2:49:20 AM9/20/14
to Henrik Johansson, golang-nuts

Because this is simplified version of the code I am writing.

What I am having is a goroutine that keeps some data and gives it to main routine via channel.

Without default in a main's select loop I would block when there are no data left, but with default I could receive fewer data than I wanted.

Julian Phillips

unread,
Sep 20, 2014, 3:29:04 AM9/20/14
to ma...@kevac.org, Henrik Johansson, golang-nuts
On 20/09/2014 07:48, ma...@kevac.org wrote:
> Because this is simplified version of the code I am writing.
>
> What I am having is a goroutine that keeps some data and gives it to
> main
> routine via channel.
>
> Without default in a main's select loop I would block when there are no
> data left, but with default I could receive fewer data than I wanted.

select + default is the wrong idiom for dealing with "end of data", you
want close.

http://play.golang.org/p/-gMkX3nm4_
http://golang.org/ref/spec#Close
http://golang.org/ref/spec#Receive_operator

--
Julian

ma...@kevac.org

unread,
Sep 20, 2014, 6:31:14 AM9/20/14
to Julian Phillips, Henrik Johansson, golang-nuts
In my case it is not end of data, it is "right now there are no more data".
--
A. Because it breaks the logical sequence of discussion
Q. Why is top posting bad?

ma...@kevac.org

unread,
Sep 20, 2014, 6:40:45 AM9/20/14
to Julian Phillips, Henrik Johansson, golang-nuts
To be more specific, I have a goroutine that has In and Out channel. Someone is sending data into In channel and goroutine accumulates this data in some array/slice. Other someone is requesting no more than n data items from channel Out. And if there are less than n items, this other someone should not block.

Reply all
Reply to author
Forward
0 new messages