golang channel

golang channel

channel类型:

  • 读写方式上来看,有以下三种:
    1. 可读可写;
    2. 仅可写;
    3. 仅可读;
  • 使用情况来看,分为传输的数据类型和是否有缓冲两种情况:
    1. 传输的数据类型:
      channel理论上可以传输任意的数据类型,根据声明时指定的数据类型,传输对应的数据,如chan int就是表示可读写int类型数据的channel;
    2. 无缓冲channel(同步channel):
      实际就是同步channel,向无缓冲channel写入数据时,如果没有消费者取出数据,则在写入这个时机就阻塞住了,这里要明确一点,此时数据并没有真正写入通道,只有当有消费者来取数据时,才会把数据传递过去。类似于邮递员送信到你家,你不在家,邮递员不会走,当你收下信,邮递员才离开。同理,消费者端也是一样,从无缓冲通道获取数据时,如果此时生产者还没有写入数据,消费者端也是阻塞住的;
    3. 有缓冲channel(异步channel):
      有缓冲通道实际就是在无缓冲通道的基础上增加了一个缓冲区,可以把无缓冲通道看成缓冲区为0,当生产者往有缓冲通道写入数据时,不会阻塞住,数据会放入缓冲区,等待消费者获取,生产者可以往下继续执行,但是缓冲区也是有大小的,这个大小是创建channel时指定的,如果消费者端一直没有取出数据,或者是取出数据的速度没有生产者生产数据的速度快,则缓冲区达到上限后,生产者此时也会阻塞住,无法将数据写入通道,只有消费者从通道取走数据,生产者才可以继续写入,消费者从有缓冲通道获取数据时,如果通道没有数据,则会阻塞住,直到通道有数据可取。

附:

调用close方法可以关闭channel,如果向一个已经关闭的channel写数据会引发panic,从一个已经关闭的channel读取数据不会引发panic,如果读取的是一个已关闭的无缓冲channel则读取到的是对应通道数据类型的零值,例如chan int,读取到的数据就是0,如果读取的是已关闭的有缓冲channel,这里就要看有缓冲channel里面是否有未取完的数据,如果有,则会先取出未读完的数据,后续再取则也是零值,所以这里可以用golang提供的多返回值方式来判断是否从通道获取到数据:
i, ok := <- ch
ok为true时,代表从通道取到了数据,i就是获取到的数据。
channel底层也是借助的同步锁机制实现的,再加上channel还需要做很多额外的数据处理,所以有些场景下直接采用sync.Mutex或者sync.WaitGroup性能会更好。

在 Go 中,可以使用 channel 实现限流,即通过 channel 的容量控制并发执行的协程数。 示例代码如下: ```go package main import ( "fmt" "time" ) func worker(id int, jobs <-chan int, results chan<- int) { for j := range jobs { fmt.Printf("worker %d 执行任务 %d\n", id, j) time.Sleep(time.Second) // 模拟任务执行时间 results <- j * 2 } } func main() { jobs := make(chan int, 100) // 创建任务 channel缓冲区大小为 100 results := make(chan int, 100) // 创建结果 channel缓冲区大小为 100 // 创建 3 个 worker 协程,即最多同时执行 3 个任务 for w := 1; w <= 3; w++ { go worker(w, jobs, results) } // 发送 9 个任务到 jobs channel for j := 1; j <= 9; j++ { jobs <- j } close(jobs) // 关闭 jobs channel,表示所有任务已发送完毕 // 收集所有结果 for a := 1; a <= 9; a++ { <-results } } ``` 在上面的示例中,我们创建了一个 `jobs` channel 和一个 `results` channel,用于分别传递任务和结果。我们创建了 3 个 worker 协程,并将 `jobs` 和 `results` channel 分别传递给它们。在主协程中,我们向 `jobs` channel 发送 9 个任务,并关闭 `jobs` channel,表示所有任务已发送完毕。然后我们收集所有结果。 由于 `jobs` channel缓冲区大小为 100,即最多可以存储 100 个任务,而 `results` channel缓冲区也为 100,即最多可以存储 100 个结果。因此,当 worker 协程数小于等于 3 时,所有任务都可以立即执行;当 worker 协程数大于 3 时,多余的任务会被存储在 `jobs` channel 中,直到有空闲的 worker 协程可以执行它们。这样就实现了限流的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值