zoukankan      html  css  js  c++  java
  • 8.4 Go select

    8.4 Go select

    Go语言引入了select关键字,用于处理异步IO问题,语义和switch特别相似。语法由select开始,每个条件由case语句来描述。每个case语句必须是IO操作

    select {
        case <-chan1:
        //如果读取到channel的数据,就执行这里
        case chan2<-1:
        //如果成功向chan2写入数据,就执行这里
        default:
        //上述都失败了,进入这里
    }
    

    案例

    使用select可以解决从管道取数据的阻塞问题

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func main() {
        //定义一个管道
        intChan := make(chan int, 10)
    
        //循环写入数据
        for i := 0; i < 10; i++ {
            intChan <- i
        }
        //定义管道,可以写入string
        strChan := make(chan string, 5)
        for i := 0; i < 5; i++ {
            //格式化后写入string数据
            strChan <- "hello" + fmt.Sprintf("%d", i)
        }
        //传统的for循环遍历,必须close关闭channel,否则造成死锁
        //但是到底关闭哪个channel,并不那么容易选择
        //加上for无线循环,匹配所有的case,直到结束return
        for {
            select {
            //如果有数据被读取到,进入这个分支,并且intChan没关闭的话,也会自动匹配下一个case
            case v := <-intChan:
                fmt.Printf("从intChan读取到数据%d
    ", v)
                time.Sleep(time.Second)
            case v2 := <-strChan:
                fmt.Printf("从strChan中读取到数据%s
    ", v2)
                time.Sleep(time.Second)
            default:
                fmt.Printf("什么也没读到,再见
    ")
                time.Sleep(time.Second)
                return
            }
        }
    
    }
    

    1.1.1. waitGroup等待组

    package main
    
    import (
        "fmt"
        "math/rand"
        "sync"
        "time"
    )
    
    func main() {
        /*
            同步等待组:WaitGourp,执行了wait的goroutine,要等待同步等待组中的其他的goroutine执行完毕。。
                内置的计数器:counter:0
                Add(),设置counter的值
                Done(),将counter减一,同Add(-1)
    
                以上两个方法可以设置counter的值,注意不能为负数,否则会引发恐慌。
    
                Wait(),哪个goroutine执行了,那么就会被阻塞,直到counter为0。解除阻塞
        */
        var wg sync.WaitGroup
        //fmt.Printf("%T
    ",wg)
        //fmt.Println(wg)
        wg.Add(2)
    
        go printNum1(&wg)
        go printNum2(&wg)
    
        wg.Wait() //main,进入阻塞状态,底层计数器为0,接触阻塞。。
        //time.Sleep(1*time.Second)
        fmt.Println("main。。接触阻塞。。结束了。。。")
    }
    
    func printNum1(wg *sync.WaitGroup) {
        rand.Seed(time.Now().UnixNano())
        for i := 1; i <= 100; i++ {
            fmt.Println("子goroutine1,i:", i)
            time.Sleep(time.Duration(rand.Intn(1000))) //
        }
        wg.Done() //计数器减一
    }
    
    func printNum2(wg *sync.WaitGroup) {
        for j := 1; j <= 100; j++ {
            fmt.Println("	子goroutine2,j:", j)
            time.Sleep(time.Duration(rand.Intn(1000)))
        }
        wg.Done()
    }
  • 相关阅读:
    3813: 奇数国|树状数组|欧拉函数
    利用Perlin nosie 完毕(PS 滤镜—— 分成云彩)
    Qt QImageReader 相似乎有bug
    android studio 更新Gradle版本号方法
    Junit测试
    POI导出
    Properties文件读取
    md5加密
    递归找出文件夹里面所有文件
    java FileReader/FileWriter读写文件
  • 原文地址:https://www.cnblogs.com/open-yang/p/11256909.html
Copyright © 2011-2022 走看看