找回密码
 立即注册
搜索
查看: 382|回复: 0

[go基础] Go语言select使用

  [复制链接]
匿名
匿名  发表于 2023-2-8 15:31 |阅读模式

select功能

  1. 每次执行select,都会只执行其中1个case或者执行default语句。
  2. 当没有case或者default可以执行时,select则阻塞,等待直到有1个case可以执行。
  3. 当有多个case可以执行时,则随机选择1个case执行。
  4. case后面跟的必须是读或者写通道的操作,否则编译出错。

select示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "log"

func main() {

	readCh := make(chan int, 1)
	writeCh := make(chan int, 1)

	y := 1
	select {
	case x := <-readCh:
		log.Printf("Read %d \n", x)
	case writeCh <- y:
		log.Printf("Write %d \n", y)
	default:
		log.Println("Do what you want.")

	}
}

运行结果:

luozhibo@bogon 04selectDemo % go run 01demo.go 
2020/03/07 15:01:39 Write 1 

说明:

  • default 不是必须的
  • 顺序执行,当执行到第二个case时,执行,有case执行,所以default不会执行

select进阶使用

三个主要特性如下:

  • nil的通道永远阻塞
  • 如何跳出for-select
  • select{}

1、nil的通道永远阻塞

当case上读一个通道时,如果这个通道时nil,则该case永远阻塞。

功能妙用:

当某个通道关闭了,不用了,则把该通道设置为nil即可。

例如:以下示例程序实现了等待两个输入通道都关闭后才退出。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// combine 两个通道都关闭后才退出
func combine(inCh1, inCh2 <-chan int) <-chan int {
	// 输出通道
	out := make(chan int)

	// 启动协程合并数据
	go func() {
		defer close(out)
		for {
			select {
			case x, open := <-inCh1:
				if !open {
					inCh1 = nil
					continue
				}
				out <- x
			case x, open := <-inCh2:
				if !open {
					inCh2 = nil
					continue
				}
				out <- x
			} // end select

			// 当ch1和ch2都关闭是才退出
			if inCh1 == nil && inCh2 == nil {
				break
			}
		} // end for
	}()

	return out
}

2、如何跳出 for-select

break 在select内失效,不能跳出for-select循环。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func consume(inCh <-chan int) {
	i := 0
	for {
		fmt.Printf("for: %d\n", i)
		select {
		case x, open := <-inCh:
			if !open {
				break // 使用break不能退出for-select循环
			}
			fmt.Printf("read: %d\n", x)
		}
		i++
	}

	fmt.Println("combine-routine exit")
}

退出方法:

  1. 在满足条件的case内,使用return,如果有结尾工作,尝试交给defer。
  2. 在select外for内使用break挑出循环,如combine函数。
  3. 使用goto。

3、select

select{}的效果等价于创建了1个通道,直接从通道读数据:

ch := make(chan int)
<-ch
永远阻塞的简洁写法

 

select的应用场景

  1. 多通道处理

  2. 无决阻塞的读、写通道。

    即使通道是带缓存的,也是存在阻塞的情况,使用select可以完美的解决阻塞读写。

  3. 设置超时时间,一旦在超时时间内无法完成,则停止处理。

 

 

原文地址:http://www.manoner.com/post/GoLand/Go%E8%AF%AD%E8%A8%80select%E4%BD%BF%E7%94%A8/
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|学习笔记

GMT+8, 2024-12-21 22:12 , Processed in 0.020535 second(s), 14 queries , APCu On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表