• golang关键字select的三个例子, time.After模拟socket/心跳超时


    golang关键字select的三个例子, time.After模拟socket/心跳超时

    例子1 select会随机选择一个可执行的case

    // 这个例子主要说明select是随机选择一个可执行的case
    func main() {
      // 定义两个chan, 用于存储数据
      // 由于我打算提前把数据存进去, 所以定义缓冲区为10
      chan1 := make(chan int, 10)
      chan2 := make(chan int, 10)
      // 在两个chan中都放入10个数据
      for i := 0; i < 10; i++ {
        chan1 <- i
      }
      for i := 0; i < 10; i++ {
        chan2 <- i
      }
      // 启动一个for循环, 无限循环
      // select的作用:
      // select会随机选择一个case, 判断该case后面的语句是否可以执行
      //     如果可以执行, 进入case的代码块中, 执行代码块
      //     如果不能只能, 则随机挑选另一个case来进行判断
      // select会持续这个随机挑选判断的过程, 直到某一个case可以被执行, 并且执行它
      // 也就是说select会阻塞在这里, 直到选择了某一个case
    
      // 特别说明: 判断的顺序是随机的, 看看第一个, 看看第二个, 再看看第二个, 再看看第一个
      // 这个和switch-case是不一样的
      fmt.Println("即将进入select")
      fmt.Println("你会发现chan 1和chan 2是随机打印的, 没有规  ")
      fmt.Println("验证了select是随机选择")
      for {
        select {
        case num1 := <-chan1:
          {
            fmt.Printf("从chan 1中取出了数据, 这是第%d次选择case 1
    ", num1)
          }
        case num2 := <-chan2:
          {
            fmt.Printf("从chan 2中取出了数据, 这是第%d次选择case 2
    ", num2)
          }
        case <-time.After(time.Second * 5):
          {
            // 请忽略这个case, 仅仅是为了退出程序
            // time.After的用法将在case 2中讲解
            fmt.Println("5秒了, 程序退出")
            return
          }
        }
      }
    }
    

    例子1

    例子2 select会阻塞, 直到某一个case可以执行 && time.After的用法

    // 这个例子主要验证select会阻塞, 直到某一个case可以执行
    // 同时也会说明time.After的用法
    func main() {
      // 创建一个通道, 在for循环中会从中取值
      dataChan := make(chan int)
    
      // 启动一个go程
      go func() {
        // 13秒之后, 我往这个dataChan中放入一个数据
        // 这个数据是什么不重要, 重要的是我放入了一个数据
        time.Sleep(time.Second * 13)
        fmt.Println("13秒到了, 往dataChan放入一个数据")
        dataChan <- 1
      }()
    
      // 这个go程只是用来打印时间和退出程序的, 对测试内容没有任何影响
      go func() {
        for i := 0; ; i++ {
          fmt.Printf("%d秒
    ", i+1)
          time.Sleep(time.Second * 1)
          if i == 22 {
            fmt.Println("测试结束, 程序退出")
            os.Exit(0)
          }
        }
      }()
    
      // 启动一个for循环, 无限循环
      for {
        // 每次循环从这里开始
        fmt.Println("-----我是select, 我开始阻塞选择啦-----")
        select {
        case <-dataChan:
          {
            // 判断是否能从dataChan这个channel中取出数据来
            // 显然前13秒是取不出来的, 因为没有人给他放数据
            fmt.Println("13秒到了, 从dataChan中取出了数据")
            fmt.Println("注意观察, 下一次select的时候, time.After会重新计时5秒")
          }
        case <-time.After(time.Second * 5):
          // time.After的作用:
          // 每次执行到select时
          // 这个time.After会开始计时
          // (如果到了)5秒后, 就会生产出一个数据, select就会认为这个case可以执行, 选择这个case
          // 如果没有到5秒, select就选择了其他case, 那么这个计时器会清零
          // 下一次循环中, 会重新进行5秒计时
          fmt.Println("5秒过去啦, time.After生产出了数据, select选择了第二个case")
        }
      }
    }
    

    例子2

    例子3 用select来判断socket/心跳超时

    // 这个例子是用select来判断socket/心跳超时
    func main() {
      // 用这个channel来模拟socket输入, 输入数据或者心跳
      socketChan := make(chan int)
      go func() {
        // 模拟输入/心跳, 每5秒输入一个数据/接收到心跳
        for i := 0; i < 2; i++ {
          time.Sleep(time.Second * 5)
          fmt.Printf("socket: 第%d个5秒到了, 我输入一个数据
    ", i+1)
          socketChan <- i
        }
        // 10秒后, socket崩溃, 不再输入数据/不再发送心跳
        time.Sleep(time.Millisecond * 1)
        fmt.Println("socket: 我崩溃啦, 没有办法继续输入数据了")
        fmt.Println("开始计算超时时间, 预计10秒后超时")
      }()
    
      // 这个go程只是用来打印时间和退出程序的, 对测试内容没有任何影响
      go func() {
        for i := 0; ; i++ {
          fmt.Printf("%d秒
    ", i+1)
          time.Sleep(time.Second * 1)
          if i == 21 {
            fmt.Println("测试结束, 程序退出")
            os.Exit(0)
          }
        }
      }()
    
      // 启动一个for循环, 无限循环
      for {
        fmt.Println("-----我是select, 我开始阻塞选择啦-----")
        select {
        case num := <-socketChan:
          {
            fmt.Printf("我是select: 我收到了socket输入 是第%d次
    ", num+1)
          }
        case <-time.After(time.Second * 10):
          {
            // 超时时间设定为10秒
            fmt.Println("我是select: 连续10秒都没有收到socket输入, 超时了")
            return
          }
        }
      }
    }
    

    例子3

  • 相关阅读:
    二叉树之小球下落
    ACM规划型。。
    经典函数看待问题。。
    用putty连接ubuntu
    minheight最小高度的实现(兼容IE6、IE7、FF)(解决IE6不兼容minheight)
    elementui里面的form表单i验证input内容已经输入不为空了,但效验还是报错不能为空
    js中10位数的时间戳必须*1000才能格式化转换
    chrome已安装Vue Devtools在控制台却无显示
    elementui使用day.js格式化后端接口里的日期时间戳
    elementui分页更改后,需要再次调用获取列表数据函数
  • 原文地址:https://www.cnblogs.com/silenzio/p/12809080.html
Copyright © 2020-2023  润新知