golang 基础(26)select

zidea · · 870 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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)
        
        }
    }
}
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 所以会跳过这个。
Golang_cyan.png

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:zidea

查看原文:golang 基础(26)select

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

870 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传