package main
import (
"fmt"
"time"
)
//单向写通道(生产者):
func producer(send chan<- int) {
for i := 0; i < 3; i++ {
send <- i
fmt.Println("生产者:", i)
}
//关闭单向写通道
close(send)
}
//单向读通道(消费者):
func consumer(recv <-chan int) {
for {
if sum, ok := <-recv; ok {
fmt.Println("接收者:", sum)
} else {
fmt.Println("接收完毕")
break
}
}
}
//单向通道的使用(生产者消费者模型)
func main() {
ch := make(chan int)
//生产者子go程
go producer(ch)
time.Sleep(time.Second)
//消费者主go程
consumer(ch)
}
运行结果:
**接收者: 0
生产者: 0
生产者: 1
接收者: 1
接收者: 2
生产者: 2
接收完毕
Process finished with exit code 0**
1,单向写通道中假若关闭通道未写,会报死锁bug,all goroutines are asleep - deadlock!为什么呢?
因为如果不关闭写通道,等读通道读不到内容的时候主go程会一直阻塞,进程一直占用系统资源不释放,所以会发生死锁
运行结果:
**接收者: 0
生产者: 0
生产者: 1
接收者: 1
接收者: 2
goroutine 1 [chan receive]:
生产者: 2
main.consumer(0xc42006a060)
/Users/zhuyp/go/src/awesomeProject1/0825test.go:67 +0x66
main.main()
/Users/zhuyp/go/src/awesomeProject1/0825test.go:82 +0x78
Process finished with exit code 2**
2,假若把consumer(ch)也改成子go程,
func main() {
ch := make(chan int)
//生产者子go程
go producer(ch)
time.Sleep(time.Second)
//消费者子go程
go consumer(ch)
//主go程
for i:=0;i<4;i++{
fmt.Println("kkkkkkk")
}
}
运行结果:
**接收者: 0
生产者: 0
生产者: 1
接收者: 1
接收者: 2
生产者: 2
kkkkkkk
kkkkkkk
kkkkkkk
kkkkkkk
Process finished with exit code 0**
这样就不会报出死锁错,因为在子go程(consumer)中读操作阻塞,主go程会争抢资源,运行主go程,主go程运行结束,切断子go程的等待资源事件,整个进程随之结束,所以不会报错
3,如果主go程中只有读channel,只有写channel或者同时有读写channel 会发生死锁