go channel原理及用法

概念

channel是goroutine(协程)间 通信的一种方式,采用CSP模型,通过数据在不同协程间的流动实现 协程间的合作; 其他协程间通信方式 包括较为常见的 内存共享,信号量等等;

实现原理

channel本质是个结构体,此结构体 维护了 3个队列,具体如下:

  1. channel的实现原理,本质上就是 协程间对 一个固定长度的环形队列 读写操作; 
  2. 队列满了就不能写入,写入的协程要暂存到 写入队列中;
  3. 队列空了就不能读取,读取的协程要暂存到 读取队列中;

具体实现细节 点击链接

根据实现原理对应的功能特点

  • 读取channel的协程会将数据从环形队列中取出; 造成的效果是 channel中的一个数据只能被一个协程读取;实现了 生产者消费者的模式(不会重复消费);
  • 当channel关闭时,会 广播的方式通知所有 读取队列中 的协程,告诉他们 此channel要关闭了; 造成的效果是 通过channel的关闭功能,实现了 协程间的广播模式;

实现如上功能特点的示例代码

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	wg := &sync.WaitGroup{}
	ch := make(chan int, 2)

	send := func() {
		for i := 0; i < 10; i++ {
			ch <- i
		}
		time.Sleep(time.Second)
		fmt.Println("关闭channel")
		close(ch)
	}

	recv := func(id int) {
		defer wg.Done()
		for {
			//fmt.Printf("进入到消费者协程 %d 的for循环\n", id)
			select {
			case i, ok := <-ch:
				if ok == true {
					fmt.Printf("消费者协程 %d 从channel中取到数据为: %d\n", id, i)
				} else {
					fmt.Printf("广播模式通知 消费者协程 %d 退出\n", id)
					return
				}
				//不加default语句 会阻塞等待
				//default:
				//fmt.Println("fu")
			}
		}
	}

	wg.Add(3)
	fmt.Println("生成3个消费者协程")
	go recv(0)
	go recv(1)
	go recv(2)
	fmt.Println("生产者发送10条数据到channel")
	send()

	wg.Wait()
}

注意点

读取channel不同方式的区别

  • 通过  for range 方式读取数据,在没有新数据时,会阻塞代码;
for i := range ch {
    fmt.Printf("通过 for range方式 阻塞读取channel中的数据,没有新数据可以读取,就阻塞住代码")
}

通过 select case default方式读取 不会阻塞代码;因为 此方式目的是 在一个地方统一管理各个channel,有数据可以读取时就执行对应的case代码; 没有channel数据可读取就执行default; 如果没有default分支,会堵塞代码;

	select {
	case i, ok := <-ch:
		if ok==true {
			fmt.Println(i)
		}else{
			fmt.Printf("channel关闭")
		}
	case i, ok := <-ch_one:
		if ok==true {
			fmt.Println(i)
		}else{
			fmt.Printf("channel关闭")
		}
    default:
	}

相关链接:

golang中channel的实现原理_Kiven_super的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值