在Go语言中,select语句类似于switch语句,但是在select语句中,case语句指的是通信,即通道上的发送或接收操作。
语法:
select{ case SendOrReceive1: // 语句 case SendOrReceive2: // 语句 case SendOrReceive3: // 语句 ....... default: // 语句
重要事项:
Select语句等待通信(发送或接收操作)准备就绪,以便在某些情况下开始。
package main import ( "fmt" "time" ) // 函数 1 func portal1(channel1 chan string) { time.Sleep(3 * time.Second) channel1 <- "Welcome to channel 1" } // 函数 2 func portal2(channel2 chan string) { time.Sleep(9 * time.Second) channel2 <- "Welcome to channel 2" } func main() { // 创建通道 R1 := make(chan string) R2 := make(chan string) // 使用goroutine调用函数1和函数2 go portal1(R1) go portal2(R2) select { // case 1 case op1 := <-R1: fmt.Println(op1) // case 2 case op2 := <-R2: fmt.Println(op2) } }
输出:
Welcome to channel 1
用法解释:在上面的程序中,portal1休眠3秒,portal2休眠9秒,在它们的休眠时间结束后,它们将准备继续进行。现在,select语句等待它们的睡眠时间,当portal2醒来时,它选择case 2并输出"Welcome to channel 1"。如果门户1在portal2之前唤醒,那么将输出“Welcome to channel 2”。
如果select语句不包含任何case语句,则该select语句将永远等待。
语法:
select{}
package main func main() { //没有任何case,将一直等待 select{ } }
输出:
fatal error: all goroutines are asleep - deadlock! goroutine 1 [select (no cases)]: main.main() /home/runner/main.go:9 +0x20 exit status 2
select语句中的default语句用于保护select语句不被阻塞。当没有case语句准备进行时,将执行此语句。
package main import "fmt" func main() { //创建通道 mychannel := make(chan int) select { case <-mychannel: default: fmt.Println("Not found") } }
输出:
Not found
select语句的阻塞意味着当尚无case语句准备就绪且select语句不包含任何default语句时,则select语句将阻塞,直到至少一个case语句或通信则可以继续。
package main func main() { //创建通道 mychannel := make(chan int) //通道尚未准备好 //并且没有默认语句 select { case <-mychannel: } }
输出:
fatal error: all goroutines are asleep - deadlock! goroutine 1 [chan receive]: main.main() /home/runner/main.go:14 +0x52 exit status 2
在select语句中,如果准备好处理多种情况,则可以随机选择其中一种。
package main import "fmt" //函数 1 func portal1(channel1 chan string){ for i := 0; i <= 3; i++{ channel1 <- "Welcome to channel 1" } } //函数 2 func portal2(channel2 chan string){ channel2 <- "Welcome to channel 2" } func main() { //创建通道 R1:= make(chan string) R2:= make(chan string) //使用goroutine方式调用函数1和2 go portal1(R1) go portal2(R2) //随机选择一种 select{ case op1:= <- R1: fmt.Println(op1) case op2:= <- R2: fmt.Println(op2) } }
输出:
Welcome to channel 2