Channel:
一、channel简介
channel即通道,是goroutine沟通的桥梁,大都是阻塞同步的,是引用类型。
1、定义和创建channel;
channel的类型:chan + 数据类型,如:chan bool
创建channel:可以通过make函数来创建channel,第一个参数是channel的类型(如:chan bool),第二个参数是channel的缓存大小(可不填)。
示例如下:
var _channel chan bool //声明channel
_channel := make(chan bool, 100) //创建channel
2、通过close关闭;
close(_channel)
3、可以通过for range来迭代操作;
for v := range _channel {
fmt.Println(v)
}
对线channel进行迭代操作时,必须在迭代的过程中明确关闭这个channel,并且保证channel被关闭成功!【调用close(_channel)】,否则会发生死锁,导致程序崩溃退出!
报错提示:fatal error: all goroutines are asleep - deadlock!
4、可以设置单向或双向通道;
双向通道:make创建的channel是双向通道,即channel值既可以存也可以取。
单向通道:分为两种:1、channel值只能存;2、channel值只能取。
5、可以设置缓存大小,在未被填满前不会发生阻塞;
无缓存是同步阻塞的,有缓存是异步的,这一点详细解释请看下一章【golang--channel缓存大小与线程阻塞的关系】
二、channel的具体操作实例:
1、通过channel来实现线程之间的通信;
完整代码如下:
package main
import (
"fmt"
"time"
)
func main() {
_channel := make(chan bool)
go func() {
fmt.Println("新线程运行开始...")
//让线程等待2秒
time.Sleep(2 * time.Second)
fmt.Println("新线程运行结束...")
_channel <- true
}()
//main函数运行到这里,会发生阻塞,直到channel获得期待的值,才会继续往下运行.
<-_channel
//由于main函数执行完毕后,函数里的局部变量都会被释放,所以我们可以不对channel进行close操作.
fmt.Println("main函数运行结束...")
}
运行结果如下:
新线程运行开始...
新线程运行结束...
main函数运行结束...
2、对channel进行迭代操作:
package main
import (
"fmt"
"time"
)
func main() {
_channel := make(chan bool)
go func() {
fmt.Println("新线程运行开始...")
//让线程等待2秒
time.Sleep(2 * time.Second)
fmt.Println("新线程运行结束...")
_channel <- true
//需要对channel执行关闭操作,否则在main函数中channel会一直进行迭代操作,永远处于阻塞状态,进而导致程序崩溃
close(_channel)
}()
//main函数运行到这里时,会发生阻塞,等待channel获得期望的值
for v := range _channel {
//当channel获得期望的值时才会执行到这里
fmt.Println("channel的值为:", v)
}
fmt.Println("main函数运行结束...")
}
运行结果如下:
新线程运行开始...
新线程运行结束...
channel的值为: true
main函数运行结束...