go并发编程之四(for-select-channel)

介绍for-select-channel的使用

文章目录

1. 定义

先理解三个概念:

没有条件的for是死循环:

for {
	//code here 
}

select-case 是专门用来轮询通道channel是否有值传递过来,有多个的时候会随机选择一个
符合条件的case,如果一个也没有且没有 default 选项,它将成为一个阻塞操作,
直到有新的值符合case为止, 有点像前面讲到的 [WaitGroup(https://blog.csdn.net/wujiangwei567/article/details/86683993)

select {
	case <-channelA :
	case b := <-channelB :
	   //oper b
}

通道

channel <- 10 //发送数据10
num := <- channel  // 接收数据

2. 使用实例

我们使用goroutine 执行多个任务,比如列表和数量的同时查询,我们不知道
谁先谁后返回,什么时候返回,什么时候完成,那么我们就可以使用 for-select 来实现数据的接收

package main

import (
	"fmt"
	"time"
)

func getTotal(total chan interface{}) {
	//假设数据库 查询了一番发现是 12条记录
	time.Sleep(3*time.Second)
	total <- 12
}

func getList(data chan interface{}){
	//假设这里做了一系列查询操作 返回一系列数据
	list := struct {
		name string
		age int
	}{
		"zhangsan",
		18,
	}
	time.Sleep(2*time.Second)
	data <- list
}


func main() {
	var total int
	var data interface{}
	done := make(chan interface{})
	defer close(done)

	go getTotal(done) //获取 总数
	go getList(done) //获取列表

	for {
		if total > 0 && data != nil {
			break
		}
		select {
		case result := <-done :
			switch result.(type) {
			case int :
				total = result.(int)
			default:
				data = result
			}
		case <-time.After(4 * time.Second) :
			fmt.Println("time out exit ")
			return
		}
	}
	fmt.Println("total is ",total)
	fmt.Println("data is ",data)
}

打印结果:

total is 12
data is {zhangsan 18}

这里用到了 定时器通道 time.After 的使用,如果所有通道到达超时时间后,仍然没有返回或退出,定时器会自动给该通道发送数据,使得 select 选择这一 case

猜你喜欢

转载自blog.csdn.net/wujiangwei567/article/details/86684246