在Go语言中,select语句就像switch语句,但是在select语句中,case语句引用通信,即通道上的发送或接收操作。
语法:
select{
case SendOrReceive1: // 语句
case SendOrReceive2: // 语句
case SendOrReceive3: // 语句
.......
default: // Statement
}
在本文中,我们将学习如何使用默认情况来避免死锁。但是首先,我们了解什么是deadlock?
死锁:当您试图从通道读取或写入数据但通道没有值时。因此,它阻塞goroutine的当前执行,并将控制传递给其他goroutine,但是如果没有其他goroutine可用或其他goroutine睡眠,由于这种情况,程序将崩溃。这种现象称为死锁。如下面的实例所示:
package main
func main() {
//创建通道
//出现死锁是因为没有goroutine在写
//因此,select语句被永远阻塞
c := make(chan int)
select {
case <-c:
}
}
输出:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
为了避免这种情况,我们在select语句中使用默认case。换句话说,当程序中出现死锁时,将执行select语句的默认情况以避免死锁。如下例所示,我们在select语句中使用默认情况以避免死锁。
package main
import "fmt"
func main() {
//创建通道
c := make(chan int)
select {
case <-c:
default:
fmt.Println("!.. Default case..!")
}
}
输出:
!.. Default case..!
当select语句只有nil通道时,也允许使用默认情况。如下面的实例所示,通道c是nil,所以默认情况下执行,如果这里的默认情况是不可用的,那么程序将永远被阻塞,死锁出现。
示例
package main
import "fmt"
func main() {
//创建通道
var c chan int
select {
case x1 := <-c:
fmt.Println("Value: ", x1)
default:
fmt.Println("Default case..!")
}
}
输出:
Default case..!