39. channel管道
2017-08-27 本文已影响118人
厚土火焱
channel 是有类型的管道,channel 的操作符是 <- ,可以用来发送或接收值。
ch <- v //赋值给管道,管道接收值
v := <- ch //管道发送值
管道的使用也是必须创建的。创建的方式是
ch := make(chan int)
管道默认情况下,在另一端准备好之前,发送和接收都会堵塞。这使得 goroutine 可以在没有明确的锁的情况下进行同步。
看一个完整的例子
package main
import "fmt"
func sum(a []int, c chan int) {
sum := 0
for _, v := range a{
sum += v
}
c <- sum
}
func main() {
a := []int{2, 0, 1, 7, 0, 8, 2, 7, 1, 7, 4}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c
fmt.Println(x, y, x + y)
}
运行结果
29 10 39
channel 是可以设置缓冲的,向有缓冲的 channel 发送数据的时候,在缓冲区满的时候才会阻塞。而当缓冲区为空的时候,接收操作会阻塞。
设置 channel 缓冲通道数量的方式如下
ch := make(chan int, 100)
这个通道数量是100。
展示一个有缓冲区的例子
package main
import "fmt"
func main() {
ch := make(chan int, 2)
ch <- 100
ch <- 5
fmt.Println(<-ch)
fmt.Println(<-ch)
}
运行结果是
100
5
本例设置了缓冲数为 2。意思是在一个 goroutine 里可以有两个传值操作,在通道值被接收前通道会被占满。如果有第三个值传入通道会发生失败。
ch <- 100
ch <- 5
ch <- 77
增加一个传入值,再运行看看,会得到如下结果
fatal error: all goroutines are asleep - deadlock!