首页 > 解决方案 > 如何将goroutine中的成功或失败结果返回给main函数和fmt.Println成功的次数

问题描述

我想用与主函数不同的函数来编写进程函数的内容。

我想用“resp, err: = client.Do (req)”计算没有导致错误的 url 数量。

我想在主函数中写 fmt.Println("Finish!") 之前的成功次数。

我应该怎么办?

func main() {
    site_list := [][]string{
        {"site1","https://www.aaaa"},
        {"site2","https://www.bbbb"},
        {"site3","https://www.cccc"},
        {"site4","https://www.dddd"},
    }

    var wg sync.WaitGroup
    maxChan := make(chan bool, 2)

    for _, v := range site_list {
        maxChan <- true
        wg.Add(1)
        go process(v[1], maxChan, &wg)
    }
    wg.Wait()
    fmt.Println("Finish!")
}

func process(site_url string, maxChan chan bool, wg *sync.WaitGroup) {
    defer wg.Done()
    defer func(maxChan chan bool) {
        <-maxChan
    }(maxChan)
    req, err := http.NewRequest("GET", site_url, nil)
    client := new(http.Client)
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("client.Doエラー" + site_url)
        return
    }
    defer resp.Body.Close()
}

标签: go

解决方案


根据我上面的评论,创建一个自定义工作项结构:

type urlItem struct {
    Name string
    Url  string
    Err  error
}

使用指针,以便process()函数可以更新底层结构:

site_list := []*urlItem{
    &urlItem{"site1", "https://www.aaaa", nil},
    &urlItem{"site2", "https://www.bbbb", nil},
    &urlItem{"site3", "https://www.cccc", nil},
    &urlItem{"site4", "https://www.dddd", nil},
}

process()然后可以安全地更新它的特定工作项(不需要任何互斥锁或同步),因为每个 go-routine 都有一个唯一的工作项。

func process(site *urlItem, maxChan chan bool, wg *sync.WaitGroup) { /* ... */ }

然后在最后统计 go-routine errors

var failCount int

for _, v := range site_list {
    if v.Err != nil {
        failCount++
    }
}

游乐场示例


推荐阅读