当前位置: 首页 > news >正文

Channel小结

一:channel的一些特性
1.尽量避免使用锁来解决临界资源安全问题
2.通道的角色必须在两个及以上
3.chan,必须要作用在两个以上的goroutine

二:通道的声明

点击查看代码
func main() {//声明+赋值var c chan intc = make(chan int, 10)/*//存,取//存c <- 1//取data := <-cfmt.Println(data)*/go func() {time.Sleep(5*time.Second)c <- 2}()//	另一个goroutine可以从通道中取数据//阻塞等待c通道写入数据。如果没人写只有读,就会一直阻塞data := <- cfmt.Println("ch data;", data)
}

三:死锁产生的情况
1.单线程无法消费channel,写入一个数据至channel,却没人来消费这个数据,会导致阻塞
2.两个channel互相需要对方的数据,但是由于判断(select监听),拿不到对方的数据
3.sync锁产生的死锁
4.接收端等待,没有写入端

四:通道关闭
我们需要将通道手动关闭的目的,是为了告诉读取端,写入端的所有数据已写入完毕
我们通常也会将for range和close进行搭配使用,for range在close关闭后且已经读取完通道内的数据后,就会自动退出for循环

点击查看代码

import "fmt"func main() {chan1 := make(chan int) //通道可以当做参数传递go test1(chan1)//读取chan中的数据/*for {time.Sleep(1 * time.Second)//判断chan状态是否关闭,如果关闭,就不会取值了data1, ok := <-chan1if !ok {fmt.Println("读取完毕")break}fmt.Println("ch data1", data1)	//这种是原始写法}*///读取chan中的数据,for 一个个取,并且会自动判断通道是否关闭for v := range chan1{time.Sleep(1*time.Second)fmt.Println(v)}fmt.Println("end")
}func test1(ch chan int) {for i := 0; i < 10; i++ {ch <- i}//关闭通道,告诉接收方,我不会再有其他数据发送到chan中了close(ch)
}

五:缓冲通道
带了一个缓冲区的通道,只有当通道全部被写满后才会被阻塞

点击查看代码
package mainimport ("fmt""time"
)func main() {//缓冲通道//缓冲区通道,放入数据,不会产生死锁,它不需要等待其他线程来拿,它可以放多个数据//如果缓冲区满了,还没有人取,还会产生死锁ch := make(chan int, 4)fmt.Println(cap(ch), len(ch))go test1(ch)for v := range ch {time.Sleep(1 * time.Second)fmt.Println("main读取数据", v)}fmt.Println("main-end")
}func test1(ch chan int) {for i := 0; i < 10; i++ {ch <- ifmt.Println("放入数据:", i)}close(ch)
}

六:单向通道
在函数中,我们通常会要求这个通道只用于读数据,当我们操作失误,这里出现了写入,这就会造成混乱
我们通常将单向通道作为函数的形参传递,只能读或者只能写

点击查看代码
package mainimport ("fmt""time"
)func main() {ch1:=make(chan int,10)ch1<-100data:=<-ch1fmt.Println(data)//单向通道ch2:=make(chan<-int,1) //只能写数据,不能读ch2<-100//data:=<-ch2  会报错//ch3:=make(<-chan int,1)  //只能读数据,不能写//ch3<-100 会报错//使用场景ch4:=make(chan int)    //可读可写go writeOnly(ch4)go readOnly(ch4)time.Sleep(5*time.Second)
}//指定函数去写,不让他读取,防止通道滥用
func writeOnly(ch chan <-int)  {//函数内部处理写数据的操作ch <- 100//尝试读操作
}//指定函数去读,不让他写入,防止通道滥用
func readOnly(ch<-chan int)  {data:=<-chfmt.Println(data)
}

七:timer定时器
可以控制程序在某个时间点做某个事情

点击查看代码
package mainimport ("fmt""time"
)func main() {timer := time.NewTimer(3 * time.Second)//创建了一个timer对象//C         <-chan Time//timer对象中的字段是一个channel,而且是一个读取的单向通道,我们将其赋值出来//timeChan:=timer.C	//这就是一个单向通道fmt.Println(<-timer.C) //打印了定时器通道中存储的时间//上面我们将里面的时间写入了通道,然后我们再通过读单向通道将其读取出来
}//定时器(提前关闭)//当我们创建一个定时器,会向Timer.C的通道中放入一个时间//当我们在下面消费这个通道的时间后,这个就不会阻塞了,直接就结束了timer2 := time.NewTimer(time.Second * 5)go func() {<-timer2.C //消费fmt.Println("end")}()timer2.Stop() //手动停止定时器
http://www.hskmm.com/?act=detail&tid=33924

相关文章:

  • 线段树历史值学习笔记
  • 连续两行fastq、连续两行MD5值如何转换为每行一个fastq一个MD5格式
  • abc428
  • 深入解析密码库低级lowlevel抽象层接口与高级highlevel抽象层接口 - 实践
  • (第五次)随机森林和xGboost
  • 23-网关选型
  • Python 爬虫实战:手把手教你抓取网页数据
  • 华为hcip总纲
  • haiku
  • Asp.Net Core 解决使用 Docker调试时出现“准备容器时发生了一个非关键性错误。项目将继续正常工作。错误为: 路径中具有非法字符。”
  • ABC 随笔
  • 大数据分析基础及应用案例:第三周学习报告 ——Matplotlib 学习报告
  • 矩阵的秩和逆
  • 2025.10 训练日志
  • 全球AI推理扩展技术解析
  • 乱七八糟的知识点
  • swtich的应用
  • AtCoder Beginner Contest 428
  • 因式分解
  • [Perl]install DateTime module
  • 模板机制作
  • 20251018 杂题 总结
  • 小马智行 VS 文远知行
  • 【做题记录】P9753 [CSP-S 2023] 消消乐
  • 南京icpc-c题:
  • 题解:P14254 分割(divide)
  • 学生信息管理系统(DAO模式重构)项目报告
  • 思科公司分析
  • 桃星中央关于重大去向问题的初步决定
  • Google Deepmind 宣布与 CFS 合作开发核聚变