go语言多线程实现方法

1.现在有如下流程:

1.检测更新
2.选择版本
3.选择区服
4.登录游戏

如下图所示:
图片描述

目前我想利用go语言进行4个线程并发进行检测,当完成其中某一个任务那么就停止当前及以前线程,如完成选择区服,停止检测更新,选择版本以及选择区服,我实在是想不到怎么搞合适,请教下各位大佬,谢谢

阅读 7k
3 个回答

你这四个步骤无法最终发起的都是网络请求,你可以使用context来实现中断请求。
四个协程共用一个context对象,当任何一个请求完成,调用cancel方法中断其他的三个请求。

简单实现了一下同时处理4个任务,并且中断执行,

原理是 4个任务中必须带有同一个context. 并且需要实现 context.Done() 的监听
http包的req.WithContext里面是实现了该监听,因此可以通过上层执行 cancel() 来取消执行
如下代码,执行结果为:

2019/07/31 15:58:08 done:  https://www.163.com
2019/07/31 15:58:08 3 <nil>
2019/07/31 15:58:08 2 Get https://www.baidu.com: context canceled
2019/07/31 15:58:08 1 Get https://www.google.com: context canceled
2019/07/31 15:58:08 4 Get https://www.taobao.com: context canceled
package main

import (
    "context"
    "log"
    "net/http"
    "sync"
)

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    cancelCh := make(chan struct{})

    var wg = sync.WaitGroup{}
    wg.Add(4)

    go func() {
        defer wg.Done()
        log.Println(1, Request(ctx, "https://www.google.com", cancelCh))
    }()
    go func() {
        defer wg.Done()
        log.Println(2, Request(ctx, "https://www.baidu.com", cancelCh))
    }()
    go func() {
        defer wg.Done()
        log.Println(3, Request(ctx, "https://www.163.com", cancelCh))
    }()
    go func() {
        defer wg.Done()
        log.Println(4, Request(ctx, "https://www.taobao.com", cancelCh))
    }()

    go func() {
        <-cancelCh
        cancel()
    }()

    wg.Wait()
}

func Request(ctx context.Context, url string, cancelCh chan struct{}) error {
    req, err := http.NewRequest(http.MethodGet, url, nil)
    if err != nil {
        return err
    }
    req = req.WithContext(ctx)
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    log.Println("done: ", url)

    close(cancelCh)
    return err
}

扩展阅读:
1 golang官方的errgroup
2 bilibili实现的errgroup

推荐问题
宣传栏