range遍历 channel 的小坑

本文探讨了Go语言中协程与无缓冲channel的交互问题。当send协程完成写入但未关闭channel时,主协程在无限读取会导致阻塞。同样,recv协程若阻塞且无释放条件,将造成协程泄露,使主协程在等待wg.Done()时阻塞。理解并避免这类陷阱对于编写高效稳定的Go程序至关重要。
摘要由CSDN通过智能技术生成


package main

import (
	"fmt"
	"sync"
)

var wg = sync.WaitGroup{}

func main() {
	c := make(chan int) //无缓冲
	wg.Add(1)
	go send(c)
	for i := range c { //send()协程写完不close的话,当send()执行结束后,主协程会阻塞,至进程崩溃
		fmt.Println(i)
	}
	//wg.Add(1)
	//go recv(c)
	wg.Wait()
}

//只能向chan里写数据
func send(c chan<- int) {
	defer wg.Done()
	for i := 0; i < 10; i++ {
		c <- i
	}
	//close(c)
}

//只能取channel中的数据
func recv(c <-chan int) {
	defer wg.Done()
	for i := range c {
		fmt.Println(i)
	}
	fmt.Println("out")
}

在这里插入图片描述
send()执行结束的话没有主动close, 主协程一直在读取c 中的数据,导致阻塞崩溃



package main

import (
	"fmt"
	"sync"
)

var wg = sync.WaitGroup{}

func main() {
	c := make(chan int) //无缓冲
	wg.Add(1)
	go send(c)
	//for i := range c { //send()协程写完不close的话,当send()执行结束后,主协程会阻塞,至进程崩溃
	//	fmt.Println(i)
	//}
	wg.Add(1)
	go recv(c)
	wg.Wait()
}

//只能向chan里写数据
func send(c chan<- int) {
	defer wg.Done()
	for i := 0; i < 10; i++ {
		c <- i
	}
	//close(c)
}

//只能取channel中的数据
func recv(c <-chan int) {
	defer wg.Done()
	for i := range c {
		fmt.Println(i)
	}
	fmt.Println("out")
}

同样会崩溃 ,recv()阻塞且没有释放条件 协程泄露,不执行wg.done(),导致主协程阻塞在wg.wait(),

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值