管道基本介绍
- channel本质是一个数据队列
- 数据是先进先出 FIFO
- 本身是线程安全的,多线程访问时不需要加锁
- 有类型的,一个string的channel只能存放string类型数据
定义和声明
使用误区
程序中必须同时有不同的goroutine对非缓冲通道进行发送和接收操作,否则会造成堵塞
func main () {
var str chan string
str = make(chan string)
str <- "hello"
fmt.Println(<- str)
}
运行错误 fatal error: all goroutines are asleep - deadlock!
非缓冲通道应在go程开启之前使用通道
func main () {
ch := make(chan int)
ch <- 100 //此处死锁 优于go程之前使用通道
go func() {
num := <-ch
fmt.Println("num=", num)
}()
//ch <- 100 //此处不死锁
time.Sleep(time.Second*3)
fmt.Println("finish")
}
通道1中调用了通道2,通道2中调用通道1会报deadlock
func main () {
ch1 := make(chan int,1 )
ch2 := make(chan int,1 )
go func() {
for {
select {
case num := <-ch1:
fmt.Println("num=", num)
ch2 <- 100
}
}
}()
for {
select {
case num := <-ch2:
fmt.Println("num=", num)
ch1 <- 300
}
}
}
channel遍历和关闭
close()函数可以用于关闭channel,关闭后的channel中如果有缓冲数据,依然可以读取,但是无法再发送数据给已关闭的channel
func main () {
ch := make(chan int,10)
for i := 0;i<10;i++ {
ch <- i
}
close(ch)
res := 0
for v := range ch {
res += v
}
fmt.Println(res)
}
如果不关闭channel,range不知道何时退出会报deadlock
读写nil channel 会报deadlock
关闭一个nil channel 会导致程序panic