• goroutine的结束与通信


    结束

    两种方法用select+channel的方法,结合WaitGroup可以同时控制多个goroutine结束,也可以在channel中传入time.After的定时器,二是利用Context里的取消函数cancel来处理,

    通信

    通信实际上就是在不同goroutine间传递数据,一是用channel传递数据,二是用context中的WithValue添加数据,用Value取数据,利用ctx.Done()监控,

    type favContextKey string
    
    func main() {
        wg := &sync.WaitGroup{}
        values := []string{"https://www.baidu.com/", "https://www.zhihu.com/"}
        ctx, cancel := context.WithCancel(context.Background())
        for _, url := range values {
            wg.Add( 1)
            // 父节点向子节点传递ctx时,用WithValue绑定了一k-v对来进行数据的传递,
            subCtx := context.WithValue(ctx, favContextKey("url"), url)
            go reqURL(subCtx, wg)
        }
        go func() {
            time.Sleep(time.Second * 3  )
            cancel()
        }()
        wg.Wait()
        fmt.Println("exit main goroutine")
    }
    func reqURL(ctx context.Context, wg *sync.WaitGroup) {
        defer wg.Done()
        // 利用Value函数从传入的ctx中取出值,进而实现了协程通信,
        url, _ := ctx.Value(favContextKey("url")).(string)
        for {
            select {
            // 根节点取消的时候,这个Done里面的chan会close,case就会收到消息,
            case <-ctx.Done():
                fmt.Printf("stop getting url:%s
    ", url)
                return
            default:
                r, err := http.Get(url)
                if r.StatusCode == http.StatusOK && err == nil {
                    body, _ := ioutil.ReadAll(r.Body)
                    subCtx := context.WithValue(ctx, favContextKey("resp"), fmt.Sprintf("%s%x", url, md5.Sum(body)))
                    wg.Add(1 )
                    go showResp(subCtx, wg)
                }
                r.Body.Close()
                //启动子goroutine是为了不阻塞当前goroutine,这里在实际场景中可以去执行其他逻辑,这里为了方便直接sleep一秒
                // doSometing()
                time.Sleep(time.Second * 1 )
            }
        }
    }
    func showResp(ctx context.Context, wg *sync.WaitGroup) {
        defer wg.Done()
        for {
            select {
            case <-ctx.Done():
                fmt.Println("stop showing resp")
                return
            default:
                //子goroutine里一般会处理一些IO任务,如读写数据库或者rpc调用,这里为了方便直接把数据打印
                fmt.Println("printing ", ctx.Value(favContextKey("resp")))
                time.Sleep(time.Second * 1 )
            }
        }
    }
    View Code

    参考:https://cloud.tencent.com/developer/article/1135275

  • 相关阅读:
    滑动切换界面---多个Activity
    172. Factorial Trailing Zeroes
    152. Maximum Product Subarray
    149. Max Points on a Line
    [转载][c++]用宏(Macro)定义一个函数
    [转载][C++]C++11 左值、右值、右值引用详解
    [转载][c++]C++中指针常量和常量指针的区别
    [转载][C++]类构造函数初始化列表
    22. Generate Parentheses
    328. Odd Even Linked List
  • 原文地址:https://www.cnblogs.com/xxswkl/p/14240337.html
Copyright © 2020-2023  润新知