Go并发原语/并发组件/go并发核心语法 之select

select 语句是 将各种channel 绑定在一起的粘合剂; 连接各种组件在一起;
select 语句可以帮助安全地将channel 与诸如取消,超时,等待和默认值之类 的概念结合在一起。

与 switch 块不同, select 块中的case 语句没有按顺序测试,如果没有满足任何条件,执行也不会失败。
如果所有channel 都没有准备好,则阻塞状态直到 。当一个channel准备好了,这个操作就会继续,它相应的语句就会执行。
func main() {
	start := time.Now()
	c := make(chan interface{})
	go func() {
		time.Sleep(5*time.Second)
		close(c)
	}()

	fmt.Println("Blocking on read ...")
	select {
		case <-c :
			fmt.Printf("Unblocked %v later.\n", time.Since(start))
	}

}
//Blocking on read ...
//Unblocked 5.00277253s later.
关于 select 一些问题?
当多个channel 有数据可供下游读取的时候会发生什么?
如没有 任何可用的channel 怎么办?
如果, 我们想做一些事情,但是没有可用的 channels 怎么办?


如果channel 同时可用会怎么样? 实验如下:

func main(){
	c1 := make(chan interface{}); close(c1)
	c2 := make(chan interface{}); close(c2)

	var c1Count, c2Count int
	for i := 1000; i>=0; i-- {
		select {
		    case <- c1:
			    c1Count++
			case <- c2:
				c2Count++
		}
	}
	fmt.Printf("c1Count: %d\nc2Count: %d\n", c1Count, c2Count)
}
//c1Count: 514
//c2Count: 487
第二个问题: 如果没有任何channel 可用,会发生什么?
第二个问题: 如果没有任何channel 可用,会发生什么?
如果没有可用的,但是你不希望 永远阻塞; 可能需要超时机制。
 */

func main(){
	var c <-chan int
	select {
		case <-c :
		case <-time.After(1 * time.Second):   //注释掉 就会 deadlock ,; 该channel 返回执行后的时间;
				fmt.Println("Time out.")
	}
}
c<- 永远不会被 解锁(unblock), 因为我们是从 nil channel 读取的,(从nil channel 读取会阻塞)
第三个问题: 当没有可用channel 时, 我们需要做些什么?
第三个问题: 当没有可用channel 时, 我们需要做些什么?
当 select 语句中的所有channel都被阻塞时候, "select" 语句也允许你调用默认语句。
 */


func main(){
	start := time.Now()
	var c1, c2 <- chan int
	select {
		case <-c1:
		case <-c2:
	    default:
		    fmt.Printf("In default after %v\n\n", time.Since(start))
	}
}
//In default after 4.612µs
//In default after 2.772µs
通常 ;会看到: default  和 for-select 循环一起使用,这允许goroutine在等待另一个goroutine上报结果的同时,可以继续执行自己的操作。
func main() {
	done := make(chan interface{})
	go func() {
		time.Sleep(5 * time.Second)
		close(done)
	}()

	workCounter := 0
loop:
	for {
		select {
		case <-done:
			break loop
		default:
		}

		//模拟工作行为
		workCounter++
		time.Sleep(1 * time.Second)
	}
	fmt.Printf("在收到停止信号停止以前,进行了%v 次 任务\n", workCounter)
}

//在收到停止信号停止以前,进行了5 次 任务
没有case 的select 将永远阻塞。
select{}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值