1、管道的定义

  1. func main(){
  2. // chan
  3. // channel
  4. // 管道中放什么类型需要提前执行
  5. // 声明int类型的管道channel
  6. var channel chan int
  7. // 初始化&赋值
  8. // make()
  9. channel :=make(chan int) //无缓冲区管道
  10. }

2、管道的读和写

  1. func main(){
  2. channel:=make(chan int) //无缓冲区管道读和写不能在同一个例程里面
  3. go func(){ //工作例程写入管道
  4. channel<-1 //将1写入管道,在写入管道后,如果还没有读管道,会发生阻塞
  5. } ()
  6. //主例程读管道
  7. num<-channel //将管道值读入变量,如果未读到数据也会发生阻塞
  8. }

注意:必须有两个例程一个写一个读,否则管道会产生死锁

3、关闭管道

  1. close(channel) //关闭管道
  2. go func(){
  3. fmt.Println(<-channel)
  4. }
  5. channel<-1

关闭之后的管道是不能够写的,但是可以读,值为空

4、判断管道是否关闭

  1. v,ok:=<-channel //用两个值来判断key是不是存在

5、使用for range 来遍历管道

  1. func main(){
  2. channe:=make(chan int)
  3. for func(){}
  4. channel<-1
  5. channel<-2
  6. channel<-3
  7. }()
  8. for num:=range channel{
  9. fmt.Println(num)
  10. }
  11. }

上面的结果会产生死锁,如果要结束死锁可以使用close来关闭管道,如下:

  1. func main(){
  2. channe:=make(chan int)
  3. for func(){}
  4. channel<-1
  5. channel<-2
  6. channel<-3
  7. close(channel)
  8. }()
  9. for num:=range channel{
  10. fmt.Println(num)
  11. }
  12. }

6、带缓冲的管道

  1. //声明方式
  2. channel := make(chan int,3) //channel可以放三个值

带缓冲的管道也可以用close的方式终止遍历而不产生死锁,也可以使用遍历同等数量的值来避免死锁。示例:

  1. package main
  2. import (
  3. "fmt"
  4. "runtime"
  5. )
  6. func main() {
  7. fmt.Println("start")
  8. channel := make(chan int)
  9. cnt := 2
  10. go func() {
  11. for i := 'A'; i <= 'Z'; i++ {
  12. fmt.Printf("%c\n", i)
  13. runtime.Gosched()
  14. }
  15. channel <- 0
  16. }()
  17. go func() {
  18. for i := 1; i <= 10; i++ {
  19. fmt.Printf("%d\n", i)
  20. runtime.Gosched()
  21. }
  22. channel <- 0
  23. }()
  24. // time.Sleep(3 * time.Second)
  25. for i := 0; i < cnt; i++ { //使用同等量的值来规避死锁
  26. <-channel
  27. }
  28. fmt.Println("end")
  29. }
文档更新时间: 2021-08-21 15:45   作者:张尚