为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
潇湘沐 2022-08-24 10:56:49
原料药 : https://jsonmock.hackerrank.com/api/articles?page=1package mainimport (    "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.WaitGroupfunc 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以上,接收被阻止。
查看完整描述

1 回答

?
偶然的你

TA贡献1841条经验 获得超3个赞

您错误地使用了等待组。


创建 goroutine 时,将其添加到等待组,并等待所有内容在单独的 goroutine 中完成,然后关闭通道:


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

        wg.Add(1)

        go makePaginatedRequest(j, comment_title_chan, false)

}

go func() {

  wg.Wait()

  close(comment_title_chan)

}()

当 goroutine 返回时,将其标记为已完成:


func makePaginatedRequest(pageNo int, chunk chan CommentTitle, pilotMode bool) int{

  defer wg.Done()

  ...


查看完整回答
反对 回复 2022-08-24
  • 1 回答
  • 0 关注
  • 88 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信