chan与select的使用及多个chan的并行处理

select语句是一种仅能用于通道发送和接收操作的专用语句

一条select语句的执行,会选择其中某一个分支执行。

select语句与switch语句类似,但选择分支的方法不同。

每个分支以关键字case开始。

每个case后只能是针对某个通道的发送语句或接收语句。

select右边直接跟左花括号。

select语句是一种仅能用于通道发送和接收操作的专用语句
一条select语句的执行,会选择其中某一个分支执行。
select语句与switch语句类型,但选择分支的方法不同。

每个分支以关键字case开始。
每个case后只能是针对某个通道的发送语句或接收语句。
select右边直接跟左花括号。


var intChan = make(chan int, 10)
var strChan = make(chan string, 10)

select{
case e1 := <-intChan:
fmt.Printf("The 1th case was seleced. e1=%v.\n",e1)
case e2 := <-strChan:
fmt.Println("The 2nd case was selectd.e2=%v.\n",e2)
default:
  fmt.Println("Default)
}
select中多个case,但并不会并行处理。
假如3个channel, select每次只能选择1个(对应ReqHandle1),当进入第一个case处理时,剩下的所有case都只能等待第一个case处理完后,才有可能进入。
假如3个channel需要同时处理,目前我是起了3个goroutine(对应ReqHandle2),每个goroutine处理一个chan。

示例:

package main

import (
	"fmt"
	"math/rand"
	"time"
)

var ChanReq0 = make(chan interface{}, 100)
var ChanReq1 = make(chan interface{}, 100)
var ChanReq2 = make(chan interface{}, 100)

func main() {
	ReqPush()
	//test case1
	//go ReqHandle1()

	//test case2
	go ReqHandle2()

	//
	for i := 0; i < 1000; i++ {
		time.Sleep(time.Second)
		fmt.Println(time.Now())
	}
	time.Sleep(10 * time.Minute)
}

func ReqPush() {
	for i := 0; i < 100; i++ {
		ChanReq0 <- string(Krand(16, KC_RAND_KIND_LOWER))
		ChanReq1 <- string(Krand(16, KC_RAND_KIND_NUM))
		ChanReq2 <- string(Krand(16, KC_RAND_KIND_UPPER))
	}
}

/*
select中多个case,但并不会并行处理,
如:进入第一个case等待处理时,剩下的所有case都只能等待第一个case处理完后,才有可能进入。
*/
func ReqHandle1() {
	for {
		select {
		case req0 := <-ChanReq0:
			//do something
			time.Sleep(10 * time.Second)
			fmt.Println("Chan0 pop:", req0)
		case req1 := <-ChanReq1:
			//do something
			time.Sleep(5 * time.Second)
			fmt.Println("Chan1 pop:", req1)
		case req2 := <-ChanReq2:
			//do something
			time.Sleep(1 * time.Second)
			fmt.Println("Chan2 pop:", req2)
		}
	}
}

/*
3个Chan,每个Chan起一个Chan起一个goroutine处理
*/
func ReqHandle2() {
	go func() {
		for {
			req := <-ChanReq0
			time.Sleep(10 * time.Second)
			fmt.Println("Chan0 pop:", req)
		}

		//db :=
	}()
	fmt.Println("xx1")
	go func() {
		for {
			req := <-ChanReq1
			time.Sleep(5 * time.Second)
			fmt.Println("Chan1 pop:", req)
		}
		//db :=
	}()
	fmt.Println("xx2")
	go func() {
		for {
			req := <-ChanReq2
			time.Sleep(1 * time.Second)
			fmt.Println("Chan2 pop:", req)
		}

		//db :=
	}()

}

const (
	KC_RAND_KIND_NUM   = 0 // 纯数字
	KC_RAND_KIND_LOWER = 1 // 小写字母
	KC_RAND_KIND_UPPER = 2 // 大写字母
	KC_RAND_KIND_ALL   = 3 // 数字、大小写字母
)

// 随机字符串
func Krand(size int, kind int) []byte {
	ikind, kinds, result := kind, [][]int{[]int{10, 48}, []int{26, 97}, []int{26, 65}}, make([]byte, size)
	is_all := kind > 2 || kind < 0
	rand.Seed(time.Now().UnixNano())
	for i := 0; i < size; i++ {
		if is_all { // random ikind
			ikind = rand.Intn(3)
		}
		scope, base := kinds[ikind][0], kinds[ikind][1]
		result[i] = uint8(base + rand.Intn(scope))
	}
	return result
}
发布了127 篇原创文章 · 获赞 24 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/Linzhongyilisha/article/details/104297813
今日推荐