I'm trying to get a better understanding of golang channels. While reading this article I'm toying with non-blocking sends and have come up with the following code:
package main
import (
"fmt"
"time"
)
func main() {
stuff := make(chan int)
go func(){
for i := 0; i < 5; i ++{
select {
case stuff <- i:
fmt.Printf("Sent %v\n", i)
default:
fmt.Printf("Default on %v\n", i)
}
}
println("Closing")
close(stuff)
}()
time.Sleep(time.Second)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
}
This will print:
Default on 0
Default on 1
Default on 2
Default on 3
Default on 4
Closing
0
0
0
0
0
While I do understand that only 0
s will get printed I do not really understand why the first send does still trigger the default
branch of the select?
What is the logic behind the behavior of a select in this case?
Example at the Go Playground
The position of default doesn't matter, it is still executed if no match found. // The default block is placed above other cases.
Is default always executed in switch Java? If there is no corresponding case value, the default clause is executed. If no case matched and there is no default clause, execution continues after the end of the switch statement.
No it is not necessary of default case in a switch statement and there is no rule of keeping default case at the end of all cases it can be placed at the starting andd middle of all other cases.
A 'switch' statement should have 'default' as the last label. Adding a 'default' label at the end of every 'switch' statement makes the code clearer and guarantees that any possible case where none of the labels matches the value of the control variable will be handled.
You never send any values to stuff
, you execute all the default cases before you get to any of the receive operations in the fmt.Println
statements. The default
case is taken immediately if there is no other operation than can proceed, which means that your loop will execute and return as quickly as possible.
You want to block the loop, so you don't need the default
case. You don't need the close
at the end either, because you're not relying on the closed channel unblocking a receive or breaking from a range
clause.
stuff := make(chan int)
go func() {
for i := 0; i < 5; i++ {
select {
case stuff <- i:
fmt.Printf("Sent %v\n", i)
}
}
println("Closing")
}()
time.Sleep(time.Second)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
fmt.Println(<-stuff)
https://play.golang.org/p/k2rmRDP38f
Notice also that the last "Sent" and the "Closing" line aren't printed, because you have no other synchronization waiting for the goroutine to finish, however that doesn't effect the outcome of this example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With