package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go func() {
fmt.Printf("func at %d\n", time.Now().UnixNano())
select {
case ch <- 1:
fmt.Println("running send")
default:
fmt.Println("running default")
}
}()
time.Sleep(100 * time.Millisecond)
fmt.Printf("main at %d\n", time.Now().UnixNano())
fmt.Println(<-ch)
}
I have researched for a day but still cannot explain why case ch <- 1:
is not ready, and the default case is selected to run. Of course, it causes deadlock!
From doc:
If the channel is unbuffered, the sender blocks until the receiver has received the value. If the channel has a buffer, the sender blocks only until the value has been copied to the buffer; if the buffer is full, this means waiting until some receiver has retrieved a value.
One way is to use this. Here's the receiver goroutine is spawned first. Also, if the receiver is not ready yet, default case will be picked up. And if it's ready, the specific case will be ready. If you run this several times, you can see either of cases happening.
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
// goroutine acts as the reciever
go func() {
fmt.Printf("main at %d\n", time.Now().UnixNano())
fmt.Println(<-ch)
}()
go func() {
fmt.Printf("func at %d\n", time.Now().UnixNano())
select {
case ch <- 1:
fmt.Println("running send")
default:
fmt.Println("running default")
}
}()
time.Sleep(1 * time.Second) // Wait for the goroutines
}
Another solution would be to use, buffered channel:
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int, 1)
go func() {
fmt.Printf("func at %d\n", time.Now().UnixNano())
select {
case ch <- 1:
fmt.Println("running send")
default:
fmt.Println("running default")
}
}()
time.Sleep(100 * time.Millisecond)
fmt.Printf("main at %d\n", time.Now().UnixNano())
fmt.Println(<-ch)
}
Also, do read this thread on stackoverflow