文章目录
道阻且长,行则将至,行而不辍,未来可期🌟。人生是一条且漫长且充满荆棘的道路,一路上充斥着各种欲望与诱惑,不断学习,不断修炼,不悔昨日,不畏将来!
GO语言也被称为21世纪的C语言,在开发与性能效率上都占据优势(Python+C)🚀。让我们一起来了解这门语言的魅力吧,希望这篇能够带给你们或多或少的帮助!!
Channel 通道的使用
通常一些语言是可以通过共享内存来实现不同线程间的数据交换,但是容易出现数据不正确的问题,一般需要通过互斥锁来确保数据的安全性,这时候就会出现性能问题
抛出问题
- 什么是Channel?
- 为什么要用Channel?
- 什么时候用Channel?
Go语言采用的是并发模型是(CSP),提倡"通过通信共享内存",而不是"通过共享内存实现通信",如果说goroutine是Go程序并发的执行体,那么channel则是它们之前的连接。channel是可以让一个goroutine发送一个特定的值到另外一个goroutine的通信机制
- 通过共享内存实现通信
- 通过通信共享内存共享(Go语言并发通信)
我们也可以理解:channel是G之间的通信的通道
定义通道
通道是chan
类型的,并且在定义通道时需要指定通道传递的数据类型
var ch chan int // 定义一个可传递int类型的通道
未初始化的channel,默认值是nil
初始化通道
需要初始化之后才能使用,通道类型需要通过内置函数"make"进行初始化才能使用
make(chan type,[缓冲区大小])
缓冲区:通道能存储的元素数量(类似数组),如果缓冲区已经满了,这时候还在往里面发送数据,则会进入阻塞状态,除非此时有其它G把缓冲区内的数据取走了,长时间阻塞则panic
通道的操作
通信共有三种操作:发送(send)、接收(receive)、关闭(close),其中发送和接收都是通过:<-符号实现的
1、发送/接收
ch := make(chan int)
ch <- 10 // 通道在前面表示,发送数据到通道ch内
注意:如果定义的通道没有缓冲区,那么则需要其它goroutine准备好读取通道的值,不然的话会出现 deadlock!异常。所以上面的程序会Panic
发送实例1、带缓冲区的发送
ch := make(chan int, 10)
ch <- 10
t := <- ch
fmt.Println(t)
打印结果
10
发送实例2、无缓存区发送,但是定义一个goroutine准备接收
ch := make(chan int)
go func() {
fmt.Println(<- ch)
}()
ch <- 10
2、关闭
ch := make(chan int, 10)
close(ch)
注意:通常会在所有数据传输、接收完成关闭通道,但需要注意的是通道不是必须关闭的,它可以被垃圾回收,如果是文件的话需要手动关闭,而通道则不是必须的
关闭通道需要注意的问题:
- 通道关闭后,发送值会panic
- 通道关闭后仍然可以取值(设计主要是为了避免通道内的数据未取完),但如果通道没有值的话会获取对应类型的零值
- 关闭一个关闭的通道会panic
ch := make(chan int, 10)
go func() {
fmt.Println(<-ch)
// 通道关闭后,只能打印对应类型的零值,这里int类型会打印0
}()
close(ch)
time.Sleep(1000)
多返回值模式
当通道关闭,获取完通道的值后,再次获取也只能获取到零值,所以这时候需要进行判断,如果通道内没有值了,我们则不再进行获取
对一个通道进行接收操作时,支持如下多返回值模式
value, ok := <- ch
- Value:从通道内获取的数据
- ok:本次是否从通道内获取数据,
true
orfalse
ch := make(chan int)
go func() {
v1,ok :=