I use this frequently. Have a function which accepts an optional channel, and reads from it in a select. Callers who don't need to send on it just pass nil, and the right thing automatically happens.
Thomas
--
select semantics are different, though, to the point where the spec
specifically calls out what a nil case in a select means.
My question is regarding a bare nil receive (or send, for that
matter). I'm having trouble imagining a case where someone does this
and it's not a serious bug.
It also says:
"A channel may be nil, which is equivalent to that case not
being present in the select statement except if a send, its
expression is still evaluated."
To me, that says, "nil channels are completely ignored in select
statements."
...but none of this helps me understand why anything other than a
panic() should occur if someone tries to send or receive from nil. It
will never do anything anyone wants.
This Go example uses blocking select (with no default case) with one output and oneinput. Go “simulates” a guard if a communication component is nil, so when not valid(line 08-09) only the input line 15 would ever execute. Line 12 will always listen (?) on thechannel, while line 15 then may send (if not nil). In the receive statement of lines 12 wehave dropped an optional second parameter, so we assume the channel does not becomeclosed.01 func Server (in <-chan int, out chan<- int) {02 value := 0 // Declaration and assignment03 valid := false // --“--04 for {05 outc := out // Always use a copy of "out"06 // If we have no value, then don't attempt07 // to send it on the out channel:08 if !valid {09 outc = nil // Makes input alone in select10 }11 select {12? case value = <-in: // RECEIVE?13 // "Overflow" if valid is already true.14 valid = true15! case outc <- value: // SEND?16 valid = false17 }18 }19 }
--
dustin
--
--
dustin
--
Again, the select documentation specifically says it ignores nil
channels, so it's special-cased already in the language. If the first
case above began to panic and the second case didn't, I don't honestly
think anyone would be surprised and the select portion of the spec would
still be correct.
Again, the select documentation specifically says it ignores nilchannels, so it's special-cased already in the language. If the first
I want both cases to do the same thing, whatever that is.And if you wantselect {case a<-b:}to panic, then I also wantselect {case a<-b:default:}to panic. Select avoids blocks, it does not somehow prevent whatever the channel normally does from happening.
https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/ChPxr_h8kUM
func maybe(b bool, c chan int) chan int {
if !b {
return nil
}
return c
}
select {
case <-maybe(val>0, p):
val--
case <-v:
val++
}
stevewang <steve....@gmail.com>
writes:
> func maybe(b bool, c chan int) chan int {
> if !b {
> return nil
> }
> return c
> }
>
> select {
> case <-maybe(val>0, p):
> val--
> case <-v:
> val++
> }
>
> So my conclusion is that it's a useful feature rather than an
> inappropriate design.
*sigh*
I understand how it's useful in select. You're providing alternatives
and nil has special consideration directly in the spec to declare it
ignored exactly in the case you have shown. I use nil in select and
find it useful.
I've been asking specifically for a case where it's not in a select
and not a bug, as the current behavior causes the current goroutine to
hold its resources and block forever with no way to ever proceed short
of killing the process.
I do understand that there are other ways to do this as well, but when
I see "select{}", I know exactly what that will do in every case.
However, when I see "<-x", I generally assume something will be read
from channel x. If you take the select out of your example above,
*sometimes* it will read and return and *sometimes* it will hang that
goroutine forever. I am having difficulty imaginging a situation where
this is desirable.
This conversation doesn't seem to be particularly constructive as it
doesn't seem that the implementation is going to change. I was just
hoping I could get some insight on a way to make something useful in a
way I'm incapable of seeing on my own.
For example, a library shouldn't panic(). But are there cases where a
library panics() and it's not a bug in the library? Yes! When the
library is doing something simple (e.g. division) where an error can
only happen if a user very obviously misuses the library (e.g. a
denominator of zero -- which is what math/big does).
stevewang <steve....@gmail.com>
writes:
> func maybe(b bool, c chan int) chan int {
> if !b {
> return nil
> }
> return c
> }
>
> select {
> case <-maybe(val>0, p):
> val--
> case <-v:
> val++
> }
>
> So my conclusion is that it's a useful feature rather than an
> inappropriate design.
*sigh*
I understand how it's useful in select. You're providing alternatives
and nil has special consideration directly in the spec to declare it
ignored exactly in the case you have shown. I use nil in select and
find it useful.
I've been asking specifically for a case where it's not in a select
and not a bug, as the current behavior causes the current goroutine to
hold its resources and block forever with no way to ever proceed short
of killing the process.
minux <minu...@gmail.com> writes:I disagree with this point, though I don't think it matters much.
> more than one people have explained why this is *NOT* a special
> consideration at all.
The spec clearly says nil is ignored. The fact that whether or not
it's ignored would produce the same effect with nil blocks is an
argument for consistency, but it's not an argument for it not being a
special case.
I didn't ask to change the behavior. I asked for an example where the
behavior is desirable.
My definition of constructive is, "can someone please show me how I
might use this feature?"
I assert that <-nil *outside of a select* is always a bug. I'm hoping
the activity on this thread dies down unless someone can show me an
example where it's not.
The big difference would just be that reading from a nil channel would no longer act like reading from an empty channel. If you look carefully, reads from other nil objects (slices and maps) act like reads from empty objects of those types, so the current nil channel behavior is at least consistent with those.
Are you able to point me to an example of code using nil channels in a select that would have been prohibitively difficult to implement in a world where attempting to receive on a nil channel in a select would panic?
var c, c1, c2, c3 chan int var i1, i2 int rec, send := true, true select { case rec && i1 = <-c1: print("received ", i1, " from c1\n") case send && c2 <- i2: print("sent ", i2, " to c2\n") case i3, ok := (<-c3): // same as: i3, ok := <-c3 if ok { print("received ", i3, " from c3\n") } else { print("c3 is closed\n") } }