美文网首页
Go: select、case的运用

Go: select、case的运用

作者: JoyHair | 来源:发表于2019-05-07 11:15 被阅读0次

    下面的例子很好的反映了select、case、协程的运作,实现的功能是:随机打印1或者2,到达超时后停止。

    实现方法:

    1个协程设置超时状态,主协程执行随机打印(随机可以用"math/rand"包实现,这里只是为了学习select、case)。
    定义1个超时状态chan,标记超时状态。

    无缓冲的channel:

    1-写入堵塞,直到其他协程读取;
    2-读取堵塞,直到其他协程写入。
    定义1个1个缓冲chan,使用select、case实现随机读写。

    带缓冲的channel:

    1-写满后再写堵塞,直到被其他协程读取;
    2-为空时去读堵塞,直到被其他协程写入;
    3-未写满情况下可一直写入;
    4-未空情况下可一直读,读一个少一个,先进先出;
    5-只要不触发满后写,空后读,可以实现针对此channel的无堵塞不限读写使用。这个例子就是用了这个处理。
    select、case针对channel的I/O进行判断,成功读取或写入就执行对应代码段,都失败就执行default对应代码段

    package main
    import (
       "fmt"
       "time"
    )
    func testSelectBase() {
       fmt.Println("select-case语句针对io起作用,写入、读取信道满足其中一个条件就可执行继续")
       i := make(chan int, 1) //定义个1个缓冲的channel,这样写入第2个值时才会堵塞,使用无缓冲的话会直接死锁
       timeout := make(chan bool)
       go func() { //设置一个超时限制下面的循环
          time.Sleep(10 * time.Second)
          timeout <- true
       }()
       fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "运行开始")//这个是go显示yyyy-mm-dd HH:MM:SS格式的语法,奇葩!据说是go发布时间...
    loop:
       for {
          select {
          case <-timeout:  //尝试读取timeout
             break loop
          default: //因为设置超时的协程需要等超时到后才给timeout写入,所以在此之前一直执行下面代码段
             select { //随机执行写入i
             case i <- 1: //成功就执行
                fmt.Printf("写入了1\t")
             case i <- 2: //成功就执行
                fmt.Printf("写入了2\t")
             }
             fmt.Printf("获取i的值是%d\n", <-i) //读取i的值
             time.Sleep(500 * time.Millisecond)
          }
       }
       fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "运行完毕")
    }
    func main() {
       testSelectBase()
    }
    

    相关文章

      网友评论

          本文标题:Go: select、case的运用

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