package main import ( "fmt" "time" ) func main() { intChan1 := make(chan int) intChan2 := make(chan int) intChan3 := make(chan int) // 协程1 go func() { for i1 := 0; i1 < 5; i1++ { intChan1 <- i1 // 向管道写入数据 time.Sleep(time.Second) <-intChan1 // 从管道读出数据 } }() // 协程2 go func() { for i2 := 0; i2 < 5; i2++ { intChan2 <- i2 // 向管道写入数据 time.Sleep(time.Second) <-intChan2 // 从管道读出数据 } }() // 协程3 go func() { for i3 := 0; i3 < 5; i3++ { intChan3 <- i3 // 向管道写入数据 time.Sleep(time.Second) <-intChan3 // 从管道读出数据 } }() // 适用死循环监控管道的读写情况 for { select { // 监控三个管道的写入情况 case i, ok := <-intChan1: if ok { fmt.Printf("监控到『管道1』写入了数据『%+v』\n", i) } else { fmt.Printf("『管道1』已关闭\n") } case i, ok := <-intChan2: if ok { fmt.Printf("监控到『管道2』写入了数据『%+v』\n", i) } else { fmt.Printf("『管道2』已关闭\n") } case i, ok := <-intChan3: if ok { fmt.Printf("监控到『管道3』写入了数据『%+v』\n", i) } else { fmt.Printf("『管道3』已关闭\n") } // 监控三个管道的读取情况 case intChan1 <- 0: fmt.Printf("监控到『管道1』读出了数据 \n") case intChan2 <- 0: fmt.Printf("监控到『管道2』读出了数据 \n") case intChan3 <- 0: fmt.Printf("监控到『管道3』读出了数据 \n") // 强烈建议设置default,避免出现deadlock,哪怕default里不做任何操作 default: } } } // ========== 输出过程·开始 ========== // // 监控到『管道1』写入了数据『0』 // 监控到『管道2』写入了数据『0』 // 监控到『管道3』写入了数据『0』 // 监控到『管道2』读出了数据 // 监控到『管道1』读出了数据 // 监控到『管道2』写入了数据『1』 // 监控到『管道1』写入了数据『1』 // 监控到『管道3』读出了数据 // 监控到『管道3』写入了数据『1』 // 监控到『管道1』读出了数据 // 监控到『管道2』读出了数据 // 监控到『管道1』写入了数据『2』 // 监控到『管道2』写入了数据『2』 // 监控到『管道3』读出了数据 // 监控到『管道3』写入了数据『2』 // 监控到『管道2』读出了数据 // 监控到『管道1』读出了数据 // 监控到『管道2』写入了数据『3』 // 监控到『管道3』读出了数据 // 监控到『管道1』写入了数据『3』 // 监控到『管道3』写入了数据『3』 // 监控到『管道1』读出了数据 // 监控到『管道2』读出了数据 // 监控到『管道1』写入了数据『4』 // 监控到『管道2』写入了数据『4』 // 监控到『管道3』读出了数据 // 监控到『管道3』写入了数据『4』 // 监控到『管道1』读出了数据 // 监控到『管道2』读出了数据 // 监控到『管道3』读出了数据 // ▎(阻塞中) // ========== 输出过程·开始 ========== // // ========== 总结 ========== // // 1、select-case和switch-case在形式上非常像,select主要使用场景就是监听管道的读写(IO),可以说是管道版的switch。 // 2、select里的case是随机执行的,而不像switch里的case是顺序执行的,若匹配到多个case只会随机执行其中一个,其余的不会执行。 // 3、如果没有匹配到case且没有设置default就会发生deadlock,所以必须设置default,哪怕不做任何操作,以避免出现deadlock问题。 // 4、select-case本身没有循环效果,所以通常需要配合for死循环使用实现监听管道的读写(IO),并且case里面可以使用break关键字, // 需要注意的是break的目标是select,而不是for死循环。
Copyright © 2024 码农人生. All Rights Reserved