channels
默认情况下,发送和接收操作在另一端准备好之前都会阻塞。这使得 Go 程可以在没有显式的锁或竞态变量的情况下进行同步。
使用前必须被创建
c := make(chan int)
可以指定缓冲区大小
cc := make(chan int,2)
package mainimport "fmt"func sum(s []int, c chan int) {sum := 0for _, v := range s {sum += v}c <- sum}func main() {s := []int{1, 2, 3, 4, 5}//使用前必须创建c := make(chan int)go sum(s[:len(s)/2], c)go sum(s[len(s)/2:], c)x, y := <-c, <-cfmt.Println(x, y, x+y) //12 3 15//使用前可以指定缓冲区大小cc := make(chan int, 5)cc <- 2cc <- 3cc <- 4fmt.Println(<-cc)fmt.Println(<-cc)fmt.Println(<-cc)// fmt.Println(<-cc) //fatal error: all goroutines are asleep - deadlock!}
close,range
close
发送者通过close(c)来关闭信道
而接收者通过
v, ok := <-ch
接收表达式分配的第二个参数来判断是否关闭,如果是false,那么就关闭
package mainimport "fmt"func fibonacci(n int, c chan int) {x, y := 0, 1for i := 0; i < n; i++ {c <- xx, y = y, x+y}close(c)// c <- x //panic: send on closed channel}func main() {c := make(chan int, 10)go fibonacci(cap(c), c)for i := range c {fmt.Println(i)}}
range
循环 for i := range c 会不断从信道接收值,直到它被关闭。
信道与文件不同,通常情况下无需关闭它们。只有在必须告诉接收者不再有需要发送的值时才有必要关闭,例如终止一个 range 循环
去掉上面程序里的close(c)会输出
0 1 …(中间是斐波拉契数列) 34 fatal error: all goroutines are asleep - deadlock!
