21、go语言channel用法


go语言的并发基于:Communication Sequential Process(CSP模型)
Don’t communicate by sharing memory; share memory by communicating(不要通过共享内存来通信,通过通信来共享内存)

chanel作为参数

func worker(id int, c chan int){
	for {
		fmt.Printf("Worker %d received %d\n",id, <- c)
	}
}
func chanDemo(){
	var c chan int = make(chan int)
	//c := make(chan int)
	go worker(0, c)
	c <- 1
	c <- 2
	time.Sleep( time.Millisecond)
}
func main(){
	chanDemo()
}

chanel作为数组

func worker(i int, c chan int){
	for{
		fmt.Printf("Worker %d received %c \n",i, <- c)
	}
}
func chanDemo(){
	var channels [10]chan int
	for i := 0; i < 10; i++{
		channels[i] = make(chan int)
		go worker(i, channels[i])
	}
	for i := 0; i < 10; i++{
		channels[i] <- 'a' + i
	}
	for i := 0; i < 10; i++{
		channels[i] <- 'A' + i
	}
	time.Sleep(time.Millisecond)
}
func main(){
	chanDemo()
}

channel作为返回值

下方使用channel作为一个函数的返回值,并指定返回的channel只能往里写数据chan<- int

func createWorker(id int) chan<- int {
	c := make(chan int)
	go func(){
		for{
			fmt.Printf("Worker %d received %c \n", id, <- c)
		}
	}()
	return c
}
func chanDemo(){
	var channels [10]chan<- int
	for i := 0; i < 10; i++ {
		channels[i] = createWorker(i)
	}
	for i := 0; i < 10; i++ {
		channels[i] <- 'a' + i
	}
	for i := 0; i < 10; i++ {
		channels[i] <- 'A' + i
	}
	time.Sleep(time.Millisecond)
}
func main(){
	chanDemo()
}

channel缓冲区

func worker(id int, c chan int){
	for {
		fmt.Printf("Worker %d received %c \n", id, <- c)
	}
}
func bufferChannelDemo(){
	//创建chan时,使用缓冲区,不用发送数据给chan后就马上使用
	c := make(chan int,3)
	go worker(0, c)
	c <- 'a'
	c <- 'b'
	c <- 'c'
	c <- 'D'
	time.Sleep( time.Millisecond)
}
func main(){
	bufferChannelDemo()
}

channel使用close

chan如果要close的话,一定要是发送方(创建方)close,而不是接收方(使用方)close

func worker(id int, c chan int){
	/*for n := range c{
		fmt.Printf("Worker %d received %d \n", id, n)
	}*/
	for {
		n, ok := <- c
		if !ok {
			break
		}
		fmt.Printf("Worker %d received %d \n", id, n)
	}
}
func bufferedChannelDemo(){
	//创建chan时,使用缓冲区,不用发送数据给chan后就马上使用
	c := make(chan int,3)
	go worker(0, c)
	c <- 'a'
	c <- 'b'
	c <- 'c'
	c <- 'D'
	close(c)
	time.Sleep( time.Millisecond)
}
func main(){
	bufferedChannelDemo()
}

range遍历channel时,不close channel

func worker(id int, c chan int){
	//使用range遍历channel时,会一直收数据,因为外部channel没有close
	for n := range c {
		fmt.Printf("Worker %d received %c\n",
			id, n)
	}
}
func createWorker(id int)chan<- int  {
	c := make(chan int)
	go worker(id, c)
	return c
}
func chanDemo(){
	var channels [10]chan<- int
	for i:=0; i<10; i++ {
		channels[i] = createWorker(i)
	}
	for i:=0; i<10; i++{
		channels[i] <- 'a' + i
	}
	for i:=0; i<10; i++{
		channels[i] <- 'A' + i
	}
	time.Sleep(time.Second)
}
func main(){
	chanDemo()
}

使用channel等待goroutine结束

type worker struct {
	in chan int
	done chan bool
}
//使用多个chan来并行完成任务
func doWorker(id int, c chan int, done chan bool){
	for n := range c{
		fmt.Printf("Worker %d received %c \n", id, n)
		//通知任务已经完成
		go func(){done <- true}()
	}
}
func createWorker(id int) worker {
	w := worker{
		in : make(chan int),
		done : make(chan bool),
	}
	go doWorker(id, w.in, w.done)
	return w
}
func chanDemo(){
	var workers [10]worker
	for i := 0; i < 10; i++ {
		workers[i] = createWorker(i)
	}
	for i, worker := range workers {
		worker.in <- 'a' + i
	}
	for _, worker := range workers {
		<- worker.done
	}
	for i := 0; i < 10; i++ {
		workers[i].in <- 'A' + i
	}
	for _, worker := range workers {
		<- worker.done
	}
}

func main(){
	chanDemo()
}

使用waitGroup等待goroutine结束

type worker struct {
	in chan int
	wg *sync.WaitGroup
}
//使用多个chan来并行完成任务
func doWorker(id int, c chan int, wg *sync.WaitGroup){
	for n := range c{
		fmt.Printf("Worker %d received %c \n", id, n)
		//通知任务已经完成
		wg.Done()
	}
}
func createWorker(id int, wg *sync.WaitGroup) worker {
	w := worker{
		in : make(chan int),
		wg : wg,
	}
	go doWorker(id, w.in, wg)
	return w
}
func chanDemo(){
	var wg sync.WaitGroup

	var workers [10]worker
	for i := 0; i < 10; i++ {
		workers[i] = createWorker(i, &wg)
	}

	wg.Add(20)//设置任务总数
	for i, worker := range workers {
		worker.in <- 'a' + i
	}
	for i := 0; i < 10; i++ {
		workers[i].in <- 'A' + i
	}
	
	//wg.Done()//每个任务做完了需调用,在worker中调用,或者说在协程中调用
	wg.Wait()//等待任务完成
}

func main(){
	chanDemo()
}

函数式编程

type worker struct {
	in chan int
	done func()
}
//使用多个chan来并行完成任务
func doWorker(id int, w worker){
	for n := range w.in{
		fmt.Printf("Worker %d received %c \n", id, n)
		//通知任务已经完成
		w.done()
	}
}
func createWorker(id int, wg *sync.WaitGroup) worker {
	w := worker{
		in : make(chan int),
		done : func(){
			wg.Done()
		},
	}
	go doWorker(id, w)
	return w
}
func chanDemo(){
	var wg sync.WaitGroup

	var workers [10]worker
	for i := 0; i < 10; i++ {
		workers[i] = createWorker(i, &wg)
	}

	wg.Add(20)//设置任务总数
	for i, worker := range workers {
		worker.in <- 'a' + i
	}
	for i := 0; i < 10; i++ {
		workers[i].in <- 'A' + i
	}
	//wg.Done()//每个任务做完了需调用,在worker中调用,或者说在协程中调用
	wg.Wait()//等待任务完成
}

func main(){
	chanDemo()
}

使用select进行调度

知识点:
1、select的使用
2、定时器的使用
3、在select中使用nil channel

chan里面不管是发数据还是收数据都会阻塞住,要是想非阻塞就使用select

examples:

func generator() chan int{
	out := make(chan int)
	go func(){
		i := 0
		for{
			time.Sleep( time.Duration(rand.Intn(1500)) * time.Millisecond)
			out <- i
			i++
		}
	}()
	return out
}

func main (){
	var c1, c2 = generator(), generator()
	for{
		select{
			case n := <- c1:
				fmt.Println("Received c1:", n)
			case n := <- c2:
				fmt.Println("Received c2:", n)
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值