Go-Select

Go里面的一个关键字,用于监听channel上的数据流动。select语句里面的每条case语句必须是一个IO操作。

select {
case <- chan1;
        //如果chan1成功读 取到数据,则进行该case语句处理。
case chan2 <- 1;
        //如果成功向chan2中写入数据,则进行case语句处理。
default;
        //如果上面都没有成功,则进入default语句处理,通常不用(会产生忙轮训)
}

代码示例:

package main
import (
    "fmt"
    "runtime"
    "time"
)
func main () {
    //定义两个channel
    ch := make(chan int)//用于通信
    quit := make(chan bool)//用于判断是否退出
    //新建一个子goroutine,用于channel写
    go func() {
        for i :=0; i < 5; i++ {
            ch <- i
            time.Sleep(time.Second)
        }
        close(ch)//关闭channel
        quit <- true//通知主goroutine是否退出
        runtime.Goexit()
    }()
    //主goroutine用于读取
    for  {
        select {
        case  num := <- ch :
            fmt.Println("读到:",num)
        case  <- quit:
            return
        }
        fmt.Println("###############")
    }
}

输出:

读到: 0
###############
读到: 1
###############
读到: 2
###############
读到: 3
###############
读到: 4
###############

斐波那契数列:

package main
import (
    "fmt"
    "runtime"
)
//打印输出Fibonacci
func fibonacci (ch <- chan int,quit <- chan bool)  {
    for {
        select {
        case num :=  <- ch://从管道中读取数据
            fmt.Print(num," ")
        case <- quit:
            runtime.Goexit()//退出子goroutine
        }
    }
}
func main () {
    //定义两个channel
    ch := make(chan int)//用于通信
    quit := make(chan bool)//用于判断主goroutine是否退出
    go fibonacci(ch,quit)//打印输出Fibonacci
    //主goroutine用于计算
    x,y := 1,1
    for i := 0; i < 20; i++ {
        ch <- x
        x, y = y, x + y
    }
    quit <- true
}

注意事项:
1、监听的case中,没有满足的监听条件,阻塞。
2、监听的case中,有多个满足监听条件,任选一个执行。
3、可以使用default来处理所有的case都不满足的条件的状况,通常不用(会产生忙轮训)。
4、select自身不带有循环机制,需要借助外层的for循环来监听。
5、break只能跳出select,类似于switch中的用法。不能使用break跳出主goroutine,如果要跳 出子goroutine,可以使用runtime.Goexit()

超时:

package main
import (
    "fmt"
    "time"
)
func main () {
    ch := make(chan int)
    quit := make(chan bool)
    //timer := time.NewTimer(time.Second*3)
    go func() {
        for {
            select {
            case num := <- ch: //这里阻塞了,因为没有写
            fmt.Println("num=",num)
            //case <- timer.C: //等待3秒后,把系统时间读取出来
            case <- time.After(3*time.Second)://等待3秒后,把系统时间读取出来
                fmt.Println("超时")
                 quit <- true//判断是否退出
                 break
            }
        }
    }()

     <- quit//主goroutine从管道中读取
}

你可能感兴趣的:(Go-Select)