乐趣区

关于golang:Select多路复用

在某些场景下咱们须要同时从多个通道接收数据。通道在接收数据时,如果没有数据能够接管将会产生阻塞,而 select 就能够同时监听一个或多个 channel,直到其中一个 channel 筹备好。

select 的应用相似于 switch 语句,它有一系列 case 分支和一个默认的分支。每个 case 会对应一个通道的通信(接管或发送)过程。select 会始终期待,直到某个 case 的通信操作实现时,就会执行 case 分支对应的语句。具体格局如下:

    select {
    case <-chan1:
       // 如果 chan1 胜利读到数据,则进行该 case 解决语句
    case chan2 <- 1:
       // 如果胜利向 chan2 写入数据,则进行该 case 解决语句
    default:
       // 如果下面都没有胜利,则进入 default 解决流程
    }
package main

import (
    "fmt"
    "time"
)

func test1(ch chan string) {time.Sleep(time.Second * 1)
    ch <- "test1"
}
func test2(ch chan string) {time.Sleep(time.Second * 2)
    ch <- "test2"
}

func main() {
    // 2 个管道
    output1 := make(chan string)
    output2 := make(chan string)
    // 跑 2 个子协程,写数据
    go test1(output1)
    go test2(output2)
    for {
        // 用 select 监控
        select {
        case s1 := <-output1:
            fmt.Println("s1=", s1)
        case s2 := <-output2:
            fmt.Println("s2=", s2)
        default:
            ticker := time.NewTicker(1 * time.Second)
            fmt.Printf("%v\n", <-ticker.C)
        }
    }
}

判断通道是否曾经存满

package main

import (
    "fmt"
    "time"
)

// 判断管道有没有存满
func main() {
    // 创立管道
    output1 := make(chan string, 1)
    // 子协程写数据
    go write(output1)
    // 取数据
    for s := range output1 {fmt.Println("res:", s)
        time.Sleep(time.Second)
    }
}

func write(ch chan string) {
    for {
        select {
        // 写数据
        case ch <- "hello":
            fmt.Println("write hello")
        default:
            fmt.Println("channel full")
        }
        time.Sleep(time.Millisecond * 500)
    }
}
退出移动版