概述

倡议先浏览 range, 非缓冲通道, 缓冲通道。

range 除了能够遍历字符串、切片、数组等数据结构外,还能够遍历通道。

语法规定

和遍历其余数据结构不同,遍历通道时没有 索引 的概念,只有值,语法如下:

for v := range ch { // v 是从通道接管到的值// do something ...}

应用规定

  1. 遍历一个空的通道 (值为 nil) 时,阻塞
  2. 遍历一个阻塞 && 未敞开的通道时,阻塞
  3. 遍历一个阻塞 && 已敞开的通道时,不做任何事件
  4. 遍历一个非阻塞 && 未敞开的通道时,就接管通道内的所有缓存数据,而后阻塞
  5. 遍历一个非阻塞 && 已敞开的通道时,就接管通道内的所有缓存数据,而后返回

例子

遍历一个空的通道

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*/

分割我