美文网首页
select详解

select详解

作者: 只争朝夕々 | 来源:发表于2020-07-05 11:46 被阅读0次

    语法具体定义参考官方定义

    https://golang.org/ref/spec#Select_statements

    select语句执行分以下一个步骤执行

    • 所有channel表达式都会被求值、所有被发送的表达式都会被求值。求值顺序:自上而下、从左到右。
    • 如果有一个或多个通信操作可以完成,则Go运行时系统会伪随机的选择一个执行。否则,如果有default分支,则执行default分支语句,如果连default都没有,则select语句会一直阻塞,直到至少有一个通信操作可以进行。

    案例分析

    所有channel表达式都会被求值、所有被发送的表达式都会被求值。求值顺序:自上而下、从左到右

    func main() {
        var ch1 chan int
        var ch2 chan int
        var chs = []chan int{ch1, ch2}
        var numbers = []int{1, 2, 3, 4, 5}
    
        getNumber := func(i int) int {
            fmt.Printf("numbers[%d]\n", i)
            return numbers[i]
        }
    
        getChan := func(i int) chan int {
            fmt.Printf("chs[%d]\n", i)
            return chs[i]
        }
    
        select {
        case getChan(0) <- getNumber(2):
            fmt.Println("1th case is selected.")
        case getChan(1) <- getNumber(3):
            fmt.Println("2th case is selected.")
        default:
            fmt.Println("default case")
        }
    }
    

    输出:

    chs[0]
    numbers[2]
    chs[1]
    numbers[3]
    default case
    
    Process finished with exit code 0
    

    如果有一个或多个通信操作可以完成,则Go运行时系统会伪随机的选择一个执行。否则,如果有default分支,则执行default分支语句,如果连default都没有,则select语句会一直阻塞,直到至少有一个通信操作可以进行

    • 所有case语句都被阻塞时,如果有default语句,执行default语句
    func main() {
        start := time.Now()
        ch1 := make(chan int)
        ch2 := make(chan int)
    
            go func() {
            time.Sleep(2 * time.Second)
            ch1 <- 3
        }()
    
        go func() {
            time.Sleep(3 * time.Second)
            ch2 <- 5
        }()
    
        fmt.Println("blocking on read...")
    
        select {
        case <-ch1:
            fmt.Printf("ch1 case...")
        case <-ch2:
            fmt.Printf("ch2 case...")
        default:
            fmt.Printf("default case...")
        }
    }
    

    输出:

    blocking on read...
    default case...
    Process finished with exit code 0
    
    • 所有case语句都被阻塞时,当没有default语句时,select阻塞等待
    func main() {
        start := time.Now()
            ch1 := make(chan int)
        ch2 := make(chan int)
    
        go func() {
            time.Sleep(2 * time.Second)
            ch1 <- 3
        }()
    
        go func() {
            time.Sleep(3 * time.Second)
            ch2 <- 5
        }()
    
        fmt.Println("blocking on read...")
    
        select {
        case <-ch1:
            fmt.Printf("ch1 case...")
        case <-ch2:
            fmt.Printf("ch2 case...")
        }
    }
    

    输出:

    blocking on read...
    ch1 case...
    Process finished with exit code 0
    
    • 当多个case语句都可以被执行时,伪随机的选择一个执行
    func main() {
        start := time.Now()
        ch1 := make(chan int)
        ch2 := make(chan int)
    
        go func() {
            time.Sleep(1 * time.Second)
            ch1 <- 3
        }()
    
        go func() {
            time.Sleep(1 * time.Second)
            ch2 <- 5
        }()
    
        fmt.Println("blocking on read...")
    
        select {
        case <-ch1:
            fmt.Printf("ch1 case...")
        case <-ch2:
            fmt.Printf("ch2 case...")
        }
    }
    

    输出:

    blocking on read...
    ch1 case...
    Process finished with exit code 0
    
    blocking on read...
    ch2 case...
    Process finished with exit code 0
    

    相关文章

      网友评论

          本文标题:select详解

          本文链接:https://www.haomeiwen.com/subject/nvtvqktx.html