猿问

当输入数量未知时如何关闭通道?

原料药 : https://jsonmock.hackerrank.com/api/articles?page=1


package main


import (

    "fmt"

    "net/http"

    "encoding/json"

    "strconv"

    "sync"

)


type ArticleResponse struct {

    Page       int `json:"page"`

    PerPage    int `json:"per_page"`

    Total      int `json:"total"`

    TotalPages int `json:"total_pages"`

    Data []Article `json:"data"`

}


type Article struct {

    Title       string      `json:"title"`

    URL         string      `json:"url"`

    Author      string      `json:"author"`

    NumComments int         `json:"num_comments"`

    StoryID     int32 `json:"story_id"`

    StoryTitle  string `json:"story_title"`

    StoryURL    string `json:"story_url"`

    ParentID    int32 `json:"parent_id"`

    CreatedAt   int         `json:"created_at"`

}


type CommentTitle struct{

    NumberOfComments int `json:"number_of_comments"`

    Title string `json:"title"`

    Page int `json:"from_page"`

}


const (

    GET_HOST_URL = "https://jsonmock.hackerrank.com/"

    PATH = "api/articles"

)


var wg sync.WaitGroup


func main(){

    comment_title_chan := make(chan CommentTitle)

    var commentTitleSlice []CommentTitle

    

    // pilot call to get total number of pages

    totalPage := makePaginatedRequest(1, comment_title_chan, true)


    // making concurrent requests to multiple pages at once

    for j:=1;j<=totalPage;j++{

        go makePaginatedRequest(j, comment_title_chan, false)

    }

}



问题陈述:


有一个 api 在查询参数中传递页码时提供数据。我需要调用所有页面并获取具有有效标题和评论数量字段的所有文章。


溶液:


步骤1:我首先对api进行试点调用以了解页面数,因为它是响应json的一部分。


第2步:我启动多个goroutines(goroutines的数量=总页数)


第3步:每个goroutine将调用相应的页面并获取数据并将其发送到数据通道。


步骤4:将通道中接收到的数据追加到切片上,切片用于进一步计算(根据文章的评论数量进行排序)


问题:我不知道记录总数 - 有多少是有效的,因此我不知道何时关闭来自发送方的通道(在我的场景中有多个发送方和单个接收方)。


我尝试再使用一个额外的信号通道,但是我什么时候才能知道所有goroutines都完成了他们的工作,以便我可以发送信号进行进一步的计算?


我甚至使用过WaitGroup,但这是在单个goroutine级别 - 我仍然无法知道所有goroutine何时完成了它的工作。


SO中还有一个类似的问题没有多大帮助:关闭未知长度的通道


更新 :在代码中,我将j循环值硬编码为20 - 这正是我遇到问题的地方。我不知道在哪里循环,如果我把它增加到50以上,接收被阻止。


潇湘沐
浏览 90回答 1
1回答

偶然的你

您错误地使用了等待组。创建 goroutine 时,将其添加到等待组,并等待所有内容在单独的 goroutine 中完成,然后关闭通道:for j:=1;j<=totalPage;j++{&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go makePaginatedRequest(j, comment_title_chan, false)}go func() {&nbsp; wg.Wait()&nbsp; close(comment_title_chan)}()当 goroutine 返回时,将其标记为已完成:func makePaginatedRequest(pageNo int, chunk chan CommentTitle, pilotMode bool) int{&nbsp; defer wg.Done()&nbsp; ...
随时随地看视频慕课网APP

相关分类

Go
我要回答