-
-
Save iamatypeofwalrus/84b6c7d946a6a4143a1d to your computer and use it in GitHub Desktop.
// An intersting pattern for testing, but you can use the check anywhere | |
import "testing" | |
func TestCheckingChannel(t *testing.T) { | |
stop := make(chan bool) | |
// Testing some fucntion that SHOULD close the channel | |
func (stop chan bool) { | |
close(chan) | |
}(stop) | |
// Make sure that the function does close the channel | |
_, ok := (<-stop) | |
// If we can recieve on the channel then it is NOT closed | |
if ok { | |
t.Error("Channel is not closed") | |
} | |
} |
The error will never occur. If the channel isn't closed the function will block forever on line 13.
It would work if you replaced line 13 with the following:
ok := true
select {
case _, ok = <-stop:
default:
}
A select
with a default
clause is a non-blocking read from the channel.
Even simpler version, lines 13-18 with:
select {
case <-stop:
default:
t.Error("Channel is not closed")
}
Hi,
I don't understand why the default clause is also needed..
A select
with no default
will block until one of the channels yields something.
Adding a default
clause ensures the select never blocks, so either the channel is closed and that case materializes (nothing happens) or the default materializes and an error is registered.
A
select
with nodefault
will block until one of the channels yields something.Adding a
default
clause ensures the select never blocks, so either the channel is closed and that case materializes (nothing happens) or the default materializes and an error is registered.
Got it thanks Noam!
The assignment is never blocking, the read from the channel is blocking. The reason it looks non-blocking to you is that the channel is always closed by the time the read operation is performed.
Try to run the function closing the channel in a go routine (just add the keyword go
at the start of line 11). In my code you'll get the result:
channel was NOT closed
While in your case you'll still get:
Result is: false
The loop you added isn't needed, as it always runs exactly once. If the channel is closed already, it'll go into the if
and break out of the loop. If the channel isn't closed (if you added the go
to line 11), it will block on line 19 until the channel is closed and then break out fo the loop.
Yes, I understood. That's why I deleted my comment. But you already replied. Sorry. And thank you 😄
👍🏻
why not to use atomic.Bool?
I have to admit that I didn't understand all of your code in the playground, but it seems more complex and slower. It also doesn't do what the original intent of this gist is: which I interpret as reading from a channel in a non-blocking way.
General remark: I don't think it's a good idea to overload the built-in close
function (the only way to close a channel).
@noamnelke I have never heard about overload in Go. the close
func in this gist is just a Closer
implementation
I didn't understand all of your code
so sad
The error will never occur. If the channel isn't closed the function will block forever on line 13.
It would work if you replaced line 13 with the following:
ok := true select { case _, ok = <-stop: default: }A
select
with adefault
clause is a non-blocking read from the channel.
Thanks , you save my day.
❤️
Line 9 should be
close(stop)
instead ofclose(chan)