30

golang 基础(26)select

 5 years ago
source link: https://studygolang.com/articles/19466?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
3m2YF3e.jpg!web

golang_real.jpg

select是Go中的一个控制结构,类似于switch语句,用于处理异步IO操作。select会监听case语句中channel的读写操作,当case中channel读写操作为非阻塞状态(即能读写)时,将会触发相应的动作。

func main(){
    c1 := make(chan string)
    c2 := make(chan string)

    go func(){
        time.Sleep(1 * time.Second)
        c1 <- "one"
    }()
    go func(){
        time.Sleep( 2 * time.Second)
        c2 <- "two"
    }()

    for i:= 0; i < 2; i++ {
        select {
            case msg1 := <- c1:
                fmt.Println("received",msg1)
            case msg2 := <- c2:
                fmt.Println("received",msg2)
        
        }
    }
}
muUV7vN.jpg!web

th (1).jpg

func main(){
    var c1, c2 chan int
    n1 := <- c1
    n2 := <- c2

    
}

我们创建两个 channel,然后想同时从 c1, c2 来接受数据,然后看 c1, c2 谁发送数据快,谁就先接受谁的数据。

func main(){
    var c1, c2 chan int
    select {
    case n := <- c1:
        fmt.Println("Received from c1:",n)
    case n := <- c2:
        fmt.Println("Received from c2:",n)
    default:
        fmt.Println("No value")
    }


}

我们用 select 来实现上面我们想要效果,不过现在 c1, c2 都是 nil,所以就会走到 default 分支。其实这就是在 channel 里面做了一个非阻塞的处理。在学习我们已经了解到 channel 无论是发数据还是数据都会互相阻塞。

如果去掉 default 就会 deadlock ,因为没有人发数据所以就造成了 deadlock

func generator() chan int {
    out := make(chan int)
    go func(){
        i := 0
        for{
            time.Sleep(
                time.Duration(rand.Intn(1500)) * time.Millisecond)
                out <- i
                i++
        }
    }()

    return out;
}

func main(){
    var c1, c2 = generator(),generator()
    select {
    case n := <- c1:
        fmt.Println("Received from c1:",n)
    case n := <- c2:
        fmt.Println("Received from c2:",n)
    
    }


}
func worker(id int, c chan int){
    for n := range c{
        fmt.Printf("Workder %d received %d\n", id, n)
    }
}

func createWorker(id int) chan<- int {
    c := make(chan int)
    go worker(id, c)
    return c
}
func generator() chan int {
    out := make(chan int)
    go func(){
        i := 0
        for{
            fmt.Println("generator")
            time.Sleep(
                time.Duration(rand.Intn(1500)) * time.Millisecond)
                out <- i
                i++
        }
    }()

    return out;
}

func main(){
    var c1, c2 = generator(),generator()
    var worker = createWorker(0)
    n := 0
    hasValue := false
    for {
        var activeWorker chan<- int
        if hasValue {
            activeWorker = worker
        }
        select {
            case n = <- c1:
                hasValue = true
            case n = <- c2:
                hasValue = true
            case activeWorker <- n:
                hasValue = false
        }
    }

}
  • 设置 n = 0,创建一个激活的 activeWorker 为 chan int 类型默认值为 nil 所以会跳过这个。
EzMRZfV.png!web

Golang_cyan.png


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK