golang for-select 优雅的退出

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

  • 启动两个做为生产者的go-routing,
  • 分别将数据生产的数据写入两个带缓冲的通道cha1,ch2
  • 分别模拟在Main go-routing和 sub go-routing中通过for-select循环读取两个通道的值并打印
  • 通过3种方式优雅的退出main go-routing
exit for-select in go-routing

https://play.golang.org/p/Ar4389-87QE

package main

import (
   // "time"
    "fmt"
)

func produce(id int, ch chan string, quitSub chan int){
        for i:=0;i< 10;i++{
        ch <- fmt.Sprintf("msg:%d:%d",id,i)
        }
        quitSub <- id
}

func main() {
    c1 := make(chan string, 1)                 //定义两个有缓冲的通道,容量为1
    c2 := make(chan string, 1)
    quitForSelect := make(chan int, 2)    //用于通知退出for select循环
    quitTag := []int{}                                  //用于读取和存储quitForSlect通道的两个值,保证两个product都写入完毕

    quitMain := make(chan bool)            //阻塞main gorouting,等待for select 处理完成

    go produce(1, c1, quitForSelect)
    go produce(2, c2, quitForSelect)

     go func(){
        for   {                //使用select来等待这两个通道的值,然后输出
            select {
            case msg1 := <- c1:
                    fmt.Println(msg1)
            case msg2 := <- c2:
                    fmt.Println(msg2)
        case q := <- quitForSelect:  
                fmt.Println("got quit tag for Gorouting id:", q)
                quitTag = append(quitTag,q)
                if len(quitTag) == 2{
                        fmt.Println("end to quit Main ")
                    quitMain <- true
                }
            }
        }
    }()

   <-quitMain
   fmt.Println("exit from main")
}
exit for-select by "break" in Main go-routing

https://play.golang.org/p/vEUvAslRqVw

package main

import (
    "fmt"
)

func produce(id int, ch chan string, quitSub chan int) {
    for i := 0; i < 10; i++ {
        ch <- fmt.Sprintf("msg:%d:%d", id, i)
    }
    quitSub <- id
}

func main() {
    c1 := make(chan string, 1) //定义两个有缓冲的通道,容量为1
    c2 := make(chan string, 1)
    quitForSelect := make(chan int, 2) //用于通知退出for select循环
    quitTag := []int{}                 //用于读取和存储quitForSlect通道的两个值,保证两个product都写入完毕

    go produce(1, c1, quitForSelect)
    go produce(2, c2, quitForSelect)

ForEnd:
    for { //使用select来等待这两个通道的值,然后输出
        select {
        case msg1 := <-c1:
            fmt.Println(msg1)
        case msg2 := <-c2:
            fmt.Println(msg2)
        case q := <-quitForSelect:
            fmt.Println("got quit tag for Gorouting id:", q)
            quitTag = append(quitTag, q)
            if len(quitTag) == 2 {
                fmt.Println("end to quit Main ")
                break ForEnd
            }
        }
    }

    fmt.Println("exit from main")
}
exit for-select by "goto" in Main go-routing

https://play.golang.org/p/GKD_NYpoMdT

package main

import (
    "fmt"
)

func produce(id int, ch chan string, quitSub chan int) {
    for i := 0; i < 10; i++ {
        ch <- fmt.Sprintf("msg:%d:%d", id, i)
    }
    quitSub <- id
}

func main() {
    c1 := make(chan string, 1) //定义两个有缓冲的通道,容量为1
    c2 := make(chan string, 1)
    quitForSelect := make(chan int, 2) //用于通知退出for select循环
    quitTag := []int{}                 //用于读取和存储quitForSlect通道的两个值,保证两个product都写入完毕

    go produce(1, c1, quitForSelect)
    go produce(2, c2, quitForSelect)

    for { //使用select来等待这两个通道的值,然后输出
        select {
        case msg1 := <-c1:
            fmt.Println(msg1)
        case msg2 := <-c2:
            fmt.Println(msg2)
        case q := <-quitForSelect:
            fmt.Println("got quit tag for Gorouting id:", q)
            quitTag = append(quitTag, q)
            if len(quitTag) == 2 {
                fmt.Println("end to quit Main ")
                goto ForEnd
            }
        }
    }
ForEnd:
    fmt.Println("go to here from for-select")

    fmt.Println("exit from main")
}

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

本文来自:简书

感谢作者:夜空一起砍猩猩

查看原文:golang for-select 优雅的退出

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

8480 次点击  ∙  4 赞  
加入收藏 微博
被以下专栏收入,发现更多相似内容
2 回复  |  直到 2021-08-25 14:18:50
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传