概述
倡议先浏览 range, 非缓冲通道, 缓冲通道。
range
除了能够遍历字符串、切片、数组等数据结构外,还能够遍历通道。
语法规定
和遍历其余数据结构不同,遍历通道时没有 索引
的概念,只有值,语法如下:
for v := range ch { // v 是从通道接管到的值// do something ...}
应用规定
- 遍历一个空的通道 (值为 nil) 时,阻塞
- 遍历一个阻塞 && 未敞开的通道时,阻塞
- 遍历一个阻塞 && 已敞开的通道时,不做任何事件
- 遍历一个非阻塞 && 未敞开的通道时,就接管通道内的所有缓存数据,而后阻塞
- 遍历一个非阻塞 && 已敞开的通道时,就接管通道内的所有缓存数据,而后返回
例子
遍历一个空的通道
package mainimport ( "fmt" "time")func main() { var done chan bool go func() { for v := range done { fmt.Printf("v = %v\n", v) break } fmt.Println("range broken") // 执行不到这里 }() time.Sleep(time.Second)}// $ go run main.go// 没有任何输入
遍历一个阻塞 && 未敞开的通道
package mainimport ( "fmt" "time")func main() { done := make(chan bool) go func() { for v := range done { fmt.Printf("v = %v\n", v) break } fmt.Println("range broken") // 执行不到这里 }() time.Sleep(time.Second)}// $ go run main.go// 没有任何输入
遍历一个阻塞 && 已敞开的通道
package mainfunc main() { ch := make(chan string) close(ch) for v := range ch { println(v) }}// $ go run main.go// 没有任何输入
遍历一个非阻塞 && 未敞开的通道
通道中无缓存数据,阻塞
package mainimport ( "fmt" "time")func main() { ch := make(chan string, 1) go func() { for v := range ch { fmt.Printf("v = %v\n", v) break } fmt.Println("range broken") // 执行不到这里 }() time.Sleep(time.Second)}// $ go run main.go// 没有任何输入
通道中有 1 个数据
package mainfunc main() { ch := make(chan string, 1) ch <- "hello world" for v := range ch { println(v) } // 代码执行不到这里 close(ch)}// $ go run main.go// 输入如下/** v = hello world*/
通道中有多个数据
package mainimport ( "fmt" "time")func main() { ch := make(chan string, 3) for i := 0; i < 3; i++ { ch <- "hello world" } go func() { for v := range ch { fmt.Printf("v = %v\n", v) } fmt.Println("range broken") // 执行不到这里 }() time.Sleep(time.Second)}// $ go run main.go// 输入如下/** v = hello world v = hello world v = hello world*/
遍历一个非阻塞 && 已敞开的通道时
通道中无缓存数据,间接返回
package mainfunc main() { ch := make(chan string, 1) close(ch) for v := range ch { println(v) }}// $ go run main.go// 没有输入
通道中有 1 个数据
package mainfunc main() { ch := make(chan string, 1) ch <- "hello world" close(ch) for v := range ch { println(v) }}// $ go run main.go// 输入如下/** hello world*/
通道中有多个数据
package mainfunc main() { ch := make(chan string, 3) for i := 0; i < 3; i++ { ch <- "hello world" } close(ch) for v := range ch { println(v) }}// $ go run main.go// 输入如下/** hello world hello world hello world*/