🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
> ### channel * 一般用来不同的groutine之间传递数据 * 带缓冲的信道可被用作信号量,例如限制吞吐量 * channel存在3种状态: * nil : 未初始化的状态,只进行了声明,或者手动赋值为nil * active : 正常的channel,可读或者可写 * closed : 已关闭,(千万不要误认为关闭channel后,channel的值是nil, 关闭的channel不能发送, 但可以接收) * channel 用来进行多个goroutine通信的,可以设置缓存大小,在未被填满前不会发生阻塞(默认为0,无缓冲) * 无缓冲的信道是一批数据一进一出, 有缓冲的信道则是一个一个存储,然后一起流出去 * select 可以处理一个或多个 channel 的发送与接收 * channel用来控制速率的,例如通信两端的速率 * channel关闭时, 不能进行发送操作, 但可以进行接收操作(在关闭通道时, 应该由发送方来控制) > ### 例子一(channel的三种形式) ~~~ go package main import ( "fmt" "time" ) func Number(ch chan int) { for i := 0; i < 10; i++ { ch <- i fmt.Println(i) } } func main() { //size = 0 有保证 : 一个无缓冲的channel给你保证被发送的信号已经被接收(因为信号接收发生在信号发送完成之前) //ch := make(chan int) //size = 1 延迟保证 : 一个 size = 1 的有缓冲 channel 提供延迟保证。它可以保证先前发送的信号已经被接收(因为第一个接收信号,发生在第二个完成的发送信号之前) //ch := make(chan int, 1) //size > 1 无保证 : 一个 size > 1 的有缓冲的 channel 不会保证发送的信号已经被接收。因为信号发送发生在信号接送完成之前。 ch := make(chan int, 3) go Number(ch) go func() { for i := 0; i < 10; i++ { <-ch time.Sleep(time.Second * 2) } }() //防止主线程过快结束 time.Sleep(time.Second * 30) } ~~~ > ### 例子二(select 处理多个channel) * 如果没有默认分支, 在不满足条件下会一直阻塞 ~~~ go package main import ( "fmt" "time" ) func Number(ch chan int) { for i := 0; i < 10; i++ { ch <- i } } func main() { ch1 := make(chan int, 1) ch2 := make(chan int, 2) ch3 := make(chan int, 3) go func() { Number(ch1) }() go func() { Number(ch2) }() go func() { Number(ch3) }() go func() { for { select { case num1 := <-ch1: fmt.Println("----TODO1-----", num1) time.Sleep(time.Second * 2) case num2 := <-ch2: fmt.Println("----TODO2-----", num2) time.Sleep(time.Second * 2) case num3 := <-ch3: fmt.Println("----TODO3-----", num3) time.Sleep(time.Second * 2) } } }() time.Sleep(time.Second * 70) } ~~~ > ### 例子三: 单向channel ~~~ go ch1 := make(chan<- int, 5) ch2 := make(<-chan int, 5) ~~~ > ### 例子四: 有序输出 ~~~ go package main import ( "fmt" ) func main() { //如何有序输出 /* for i := 0; i < 10; i++ { go func() { fmt.Println(i) }() } */ /* for i := 0; i < 10; i++ { go func(n int) { fmt.Println(n) }(i) } */ ch := make(chan int) go func() { for i := 0; i < 10; i++ { ch <- i } }() for { select { case n := <-ch: fmt.Println(n) default: } } } ~~~