面试题答案
一键面试select语句执行逻辑
在Go语言中,当select
语句中有多个通道操作(读或写)准备好时:
- 随机选择:
select
会随机选择一个准备好的通道操作来执行。这种随机选择机制避免了某个通道操作总是被优先执行的“饥饿”问题。 - 阻塞:如果没有任何通道操作准备好,
select
语句会阻塞,直到至少有一个通道操作准备好。 - 默认分支:如果有
default
分支,当没有其他通道操作准备好时,default
分支会立即执行,select
语句不会阻塞。
并发任务调度示例
以下是一个简单的示例,展示如何利用select
语句进行并发任务调度:
package main
import (
"fmt"
"time"
)
func task1(ch chan string) {
time.Sleep(2 * time.Second)
ch <- "Task 1 completed"
}
func task2(ch chan string) {
time.Sleep(1 * time.Second)
ch <- "Task 2 completed"
}
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go task1(ch1)
go task2(ch2)
select {
case result := <-ch1:
fmt.Println(result)
case result := <-ch2:
fmt.Println(result)
}
}
在上述示例中:
- 启动两个并发任务
task1
和task2
,分别向ch1
和ch2
通道发送完成信息。 task1
会睡眠2秒,task2
会睡眠1秒。select
语句会随机选择一个准备好的通道操作执行。由于task2
先完成,通常情况下会先打印Task 2 completed
。但如果多次运行,也有可能出现打印Task 1 completed
的情况,这体现了select
的随机选择特性。通过这种方式,可以在多个并发任务之间进行调度,优先处理最先完成的任务。