[TOC]
select是Go语言中的一个控制语句,它有select,case, default共同构成,与switch的书写方式类似。**select只用来操作的channel的读写操作**。
*select 的特性*
1. 如果只有一个 case 语句评估通过,那么就执行这个case里的语句
2. 如果有多个 case 语句评估通过,那么通过随机的方式随机选一个
3. 如果 default 外的 case 语句都没有通过评估,那么执行 default 里的语句
4. 如果没有 default,那么 代码块会被阻塞,直到有一个 case 通过评估;否则一直阻塞
## 示例1(多路select复用)
```go
var (
swg sync.WaitGroup
)
var ch1 = make(chan int, 3)
var ch2 = make(chan string, 3)
// 生产数据
func testProducer(i int) {
defer swg.Done()
// 多个case都符合的话,随机选择一个case执行
select {
case ch1 <- i:
fmt.Printf("ch1 send %v\n", i)
case ch2 <- fmt.Sprintf("test%02d", i):
fmt.Printf("ch2 send %v\n", fmt.Sprintf("test%02d", i))
}
}
// 消费数据
func testConsumer() {
defer swg.Done()
select {
case i := <-ch1:
fmt.Printf("ch1 received is %v\n", i)
case s := <-ch2:
fmt.Printf("ch2 received is %v\n", s)
}
}
func main() {
for i := 0; i < 10; i++ {
swg.Add(1)
go testProducer(i)
}
for i := 0; i < 4; i++ {
swg.Add(1)
go testConsumer()
}
swg.Wait()
}
// 运行结果
// ch1 send 3
// ch1 send 0
// ch1 send 2
// ch2 send test09
// ch2 received is test09
// ch1 received is 2
// ch2 send test01
// ch1 received is 3
// ch1 received is 0
// ch2 send test04
// ch1 send 7
// ch2 send test05
// ch1 send 8
// ch1 send 6
```
## 示例2(超时案例)
```go
package main
import (
"fmt"
"sync"
"time"
)
var (
swg sync.WaitGroup
)
func sendChan(ch chan string) {
swg.Add(1)
go func() {
for i := 0; i < 5; i++ {
// 休眠 i 秒
for j := 0; j < i; j++ {
time.Sleep(time.Millisecond * 1000)
}
ch <- fmt.Sprintf("chan%02d", i)
}
swg.Done()
}()
}
func main() {
ch := make(chan string, 5)
defer close(ch)
defer swg.Wait()
sendChan(ch)
for j := 0; j < 5; j++ {
select {
case s := <-ch:
fmt.Printf("ch received %v\n", s)
case <-time.After(time.Second * 3):
fmt.Println("Channel no data for more than three seconds")
return
}
}
}
// 运行结果
// ch received chan00
// ch received chan01
// ch received chan02
// Channel no data for more than three seconds
```
- Golang简介
- 开发环境
- Golang安装
- 编辑器及快捷键
- vscode插件
- 第一个程序
- 基础数据类型
- 变量及匿名变量
- 常量与iota
- 整型与浮点型
- 复数与布尔值
- 字符串
- 运算符
- 算术运算符
- 关系运算符
- 逻辑运算符
- 位运算符
- 赋值运算符
- 流程控制语句
- 获取用户输入
- if分支语句
- for循环语句
- switch语句
- break_continue_goto语法
- 高阶数据类型
- pointer指针
- array数组
- slice切片
- slice切片扩展
- map映射
- 函数
- 函数定义和调用
- 函数参数
- 函数返回值
- 作用域
- 函数形参传递
- 匿名函数
- 高阶函数
- 闭包
- defer语句
- 内置函数
- fmt
- strconv
- strings
- time
- os
- io
- 文件操作
- 编码
- 字符与字节
- 字符串
- 读写文件
- 结构体
- 类型别名和自定义类型
- 结构体声明
- 结构体实例化
- 模拟构造函数
- 方法接收器
- 匿名字段
- 嵌套与继承
- 序列化
- 接口
- 接口类型
- 值接收者和指针接收者
- 类型与接口对应关系
- 空接口
- 接口值
- 类型断言
- 并发编程
- 基本概念
- goroutine
- channel
- select
- 并发安全
- 练习题
- 第三方库
- Survey
- cobra