Select 选择结构

优质
小牛编辑
143浏览
2023-12-01

select 是 Go 中的一个控制结构,类似于 switch 语句,用于处理异步 IO 操作

  • 如果有多个case都可以运行,select 会随机选出一个执行,其他不会执行。
  • 如果没有可运行的case语句,且有 default 语句,那么就会执行 default 的动作。
  • 如果没有可运行的case语句,且没有 default 语句,select 将阻塞,直到某个 case 通信可以运行
	select {
	case IO操作1:
		IO操作1读取或写入成功就执行
	case IO操作2:
		IO操作2读取或写入成功就执行
	default:
		如果上面case都没有成功,则进入default处理流程
	}

注意点:

  • select 的 case 后面必须是一个 IO 操作
  • 一般情况下使用 select 结构不用写 default
package main

import (
	"fmt"
	"time"
)
func main() {
	// 创建管道
	var myCh = make(chan int)
	var exitCh = make(chan bool)

	// 生产数据
	go func() {
		for i:=0;i <10;i++{
			myCh<-i
			time.Sleep(time.Second)
		}
		//close(myCh)
		exitCh<-true
	}()

	// 读取数据
	for{
		fmt.Println("读取代码被执行了")
		select {
		case num:= <-myCh:
			fmt.Println("读到了", num)
		case <-exitCh:
			//break // 没用, 跳出的是select
			return
		}
		fmt.Println("-----------")
	}
}

select 应用场景

  • 实现多路监听
  • 实现超时处理
package main
import (
	"fmt"
	"runtime"
	"time"
)

func main() {
	// 1.创建管道
	myCh := make(chan int, 5)
	exitCh := make(chan bool)

	// 2.生成数据
	go func() {
		for i:=0; i<10; i++ {
			myCh<-i
			time.Sleep(time.Second * 3)
		}
	}()

	// 3.获取数据
	go func() {
		for{
			select {
			case num:= <-myCh:
				fmt.Println(num)
			case <-time.After(time.Second * 2):
				exitCh<-true
				runtime.Goexit()
			}
		}
	}()

	<-exitCh
	fmt.Println("程序结束")
}