用法
- 超时控制
- 取最快的结果
- 限制最大并发数
- for…range 优先
- 多个 goroutine 同步响应
- 非阻塞的 select
- for{select{}} 终止
1.超时控制
// 利用 time.After 实现func main() { done := do() select { case <-done: // logic case <-time.After(3 * time.Second): // timeout }}func do() <-chan struct{} { done := make(chan struct{}, 1) go func() { // do something // ... done <- struct{}{} }() return done}
2.取最快的结果
比较常见的一个场景是重试,第一个请求在指定超时时间内没有返回结果,这时重试第二次,取两次中最快返回的结果使用。
超时控制在上面有,下面代码部分就简单实现调用多次了。
func main() { ret := make(chan string, 3) for i := 0; i < cap(ret); i++ { go call(ret) } fmt.Println(<-ret)}func call(ret chan<- string) { // do something // ... ret <- "result"}
3.限制最大并发数
// 最大并发数为 2limits := make(chan struct{}, 2)for i := 0; i < 10; i++ { go func() { // 缓冲区满了就会阻塞在这 limits <- struct{}{} do() <-limits }()}
4.for…range 优先
for … range c { do } 这种写法相当于 if _, ok := <-c; ok { do }
func main() { c := make(chan int, 20) go func() { for i := 0; i < 10; i++ { c <- i } close(c) }() // 当 c 被关闭后,取完里面的元素就会跳出循环 for x := range c { fmt.Println(x) }}
5.多个 goroutine 同步响应
func main() { c := make(chan struct{}) for i := 0; i < 5; i++ { go do(c) } close(c)}func do(c <-chan struct{}) { // 会阻塞直到收到 close <-c fmt.Println("hello")}
6.非阻塞的 select
select 本身是阻塞的,当所有分支都不满足就会一直阻塞,如果想不阻塞,那么一个什么都不干的 default 分支是最好的选择
select {case <-done: returndefault: }
7.for{select{}} 终止
尽量不要用 break label 形式,而是把终止循环的条件放到 for 条件里来实现
for ok { select { case ch <- 0: case <-done: ok = false }}
文章来源:智云一二三科技
文章标题:golang之channel用法
文章地址:https://www.zhihuclub.com/7460.shtml