golang中channel的用法

参考:https://www.jianshu.com/p/066455276de7

channel有点类似于管道,它在goroutine同步与通信中,有着起承转合的作用,同时也是Golang实现CSP模型的关键

package main

func main() { senderOnly := make(chan<- int) // 只能用来发送(管道的入口,只进不出) receiverOnly := make(<-chan int) // 只能用来接收(管道的出口,只出不进) unbuffer := make(chan int) // 无缓冲可收发 buffer := make(chan int, 2) // 无缓冲可收发 println(senderOnly, receiverOnly, unbuffer, buffer) } 

以下是channel的一些使用场景

等待goroutine完成

package main

func main() { println("start main") ch := make(chan bool) go func() { println("come into goroutine") ch <- true }() println("do something else") <-ch close(ch) println("end main") } 

在playground中运行
打印结果:

start main
do something else
come into goroutine
end main

多个goroutine协同

三个功能不相关的goroutine最后结果要汇总累加到result

package main

func main() { println("start main") ch := make(chan int) var result int go func() { println("come into goroutine1") var r int for i := 1; i <= 10; i++ { r += i } ch <- r }() go func() { println("come into goroutine2") var r int = 1 for i := 1; i <= 10; i++ { r *= i } ch <- r }() go func() { println("come into goroutine3") ch <- 11 }() for i := 0; i < 3; i++ { result += <-ch } close(ch) println("result is:", result) println("end main") } 

在playground中运行
其中一组打印结果:

start main
come into goroutine3
come into goroutine2
come into goroutine1
result is: 3628866 end main 

Select

两个goroutine无直接关联,但其中一个先达到某一设定条件便退出或超时退出

package main

import "time"

func main() { println("start main") cond1 := make(chan int) cond2 := make(chan uint64) go func() { for i := 0; ; i++ { cond1 <- i } }() go func() { var i uint64 for ; ; i++ { cond2 <- i } }() endCond := false for endCond != true { select { case a := <-cond1: if a > 99 { println("end with cond1") endCond = true } case b := <-cond2: if b == 100 { println("end with cond2") endCond = true } case <-time.After(time.Microsecond): println("end with timeout") endCond = true } } println("end main") } 

在playground中运行
其中打印结果有可能是:

start main
end with cond1
end main

也有可能是:

start main
end with timeout
end main

也可能是:

start main
end with cond2
end main

这说明循环100次大概需要1微秒的时间

扫描二维码关注公众号,回复: 10569024 查看本文章

channel与range

package main

import "fmt"

func main() { println("start main") ch := make(chan int, 4) go func() { for i := 0; i < 10; i++ { ch <- i } // 如果不关闭channel,会引发panic close(ch) }() for v := range ch { fmt.Println(v) } println("end main") } 

打印结果为:

start main
0
1
2
3
4 5 6 7 8 9 end main 

无缓冲channel

package main

func main() { var ch = make(chan int) ch <- 1 println(<-ch) } 

在playground中运行
打印结果为:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]: main.main() /tmp/sandbox117018544/main.go:5 +0x60 

死锁了,为什么会这样呢,因为ch是一个无缓冲的channel,在执行到ch <- 1就阻塞了当前goroutine(也就是main函数所在的goroutine),后面打印语句根本没机会执行

稍加修改即能正常运行
在playground中运行

package main

func main() { var ch = make(chan int) go func() { ch <- 1 println("sender") }() println(<-ch) } 

因为此时ch既有发送也有接收而且不在同一个goroutine里面,此时它们不会相互阻塞



作者:wu_sphinx
链接:https://www.jianshu.com/p/066455276de7
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自www.cnblogs.com/show58/p/12654431.html