dty47696 2018-02-17 16:11
浏览 42
已采纳

Goroutines和相关函数

there I am having some fun with GO and am just very curious about something I am trying to achieve. I have a package here that just gets a feed from Reddit noting special. When I receive the parent JSON file I would then like to retrieve child data. If you see the code below I launch a series of goroutines which I then block, waiting for them to finish using the sync package. What I would like is once the first series of goroutines finish the second series of goroutines using the previous results. There are a few was I was thinking such as for loop and switch statement. But what is the best and most efficient way to do this

func (m redditMatcher) retrieve(dataPoint *collect.DataPoint) (*redditCommentsDocument, error) {
    if dataPoint.URI == "" {
        return nil, errors.New("No datapoint uri provided")
    }

    // Get options data -> returns empty struct
    // if no options are present
    options := m.options(dataPoint.Options)
    if len(options.subreddit) <= 0 {
        return nil, fmt.Errorf("Matcher fail: Reddit - Subreddit option manditory
")
    }

    // Create an buffered channel to receive match results to display.
    results := make(chan *redditCommentsDocument, len(options.subreddit))

    // Generte requests for each subreddit produced using
    // goroutines concurency model
    for _, s := range options.subreddit {
        // Set the number of goroutines we need to wait for while
        // they process the individual subreddit.
        waitGroup.Add(1)
        go retrieveComment(s.(string), dataPoint.URI, results)
    }

    // Launch a goroutine to monitor when all the work is done.
    waitGroup.Wait()

    // HERE I WOULD TO CALL ANOTHER SERIES OFF GOROUTINES
    for commentFeed := range results {
        // HERE I WOULD LIKE TO CALL GO ROUTINES USING THE RESULTS
        // PROVIDED FROM THE PREVIOUS FUNCTIONS
        waitGroup.Add(1)
        log.Printf("%s

", commentFeed.Kind)
    }

    waitGroup.Wait()
    close(results)

    return nil, nil
}
  • 写回答

1条回答 默认 最新

  • dongzha2525 2018-02-24 05:01
    关注

    If you want to wait for all of the first series to complete, then you can just pass in a pointer to your waitgroup, wait after calling all the first series functions (which will call Done() on the waitgroup), and then start the second series. Here's a runnable annotated code example that does that:

    package main
    
    import(
        "fmt"
        "sync"
        "time"
    )
    
    func first(wg *sync.WaitGroup) {
        defer wg.Done()
        fmt.Println("Starting a first")
        // do some stuff... here's a sleep to make some time pass
        time.Sleep(250 * time.Millisecond)
        fmt.Println("Done with a first")
    }
    
    func second(wg *sync.WaitGroup) {
        defer wg.Done()
        fmt.Println("Starting a second")
        // do some followup stuff
        time.Sleep(50 * time.Millisecond)
        fmt.Println("Done with a second")
    }
    
    func main() {
        wg := new(sync.WaitGroup) // you'll need a pointer to avoid a copy when passing as parameter to goroutine function
    
        // let's start 5 firsts and then wait for them to finish
        wg.Add(5)
        go first(wg)
        go first(wg)
        go first(wg)
        go first(wg)
        go first(wg)
        wg.Wait()
    
        // now that we're done with all the firsts, let's do the seconds
        // how about two of these
        wg.Add(2)
        go second(wg)
        go second(wg)
        wg.Wait()
    
        fmt.Println("All done")
    }
    

    It outputs:

    Starting a first
    Starting a first
    Starting a first
    Starting a first
    Starting a first
    Done with a first
    Done with a first
    Done with a first
    Done with a first
    Done with a first
    Starting a second
    Starting a second
    Done with a second
    Done with a second
    All done
    

    But if you want a "second" to start as soon as a "first" has finished, just have the seconds executing blocking receive operators on the channel while the firsts are running:

    package main
    
    import(
        "fmt"
        "math/rand"
        "sync"
        "time"
    )
    
    func first(res chan int, wg *sync.WaitGroup) {
        defer wg.Done()
        fmt.Println("Starting a first")
        // do some stuff... here's a sleep to make some time pass
        time.Sleep(250 * time.Millisecond)
        fmt.Println("Done with a first")
        res <- rand.Int() // this will block until a second is ready
    }
    
    func second(res chan int, wg *sync.WaitGroup) {
        defer wg.Done()
        fmt.Println("Wait for a value from first")
        val := <-res // this will block until a first is ready
        fmt.Printf("Starting a second with val %d
    ", val)
        // do some followup stuff
        time.Sleep(50 * time.Millisecond)
        fmt.Println("Done with a second")
    }
    
    func main() {
        wg := new(sync.WaitGroup) // you'll need a pointer to avoid a copy when passing as parameter to goroutine function
        ch := make(chan int)
    
        // lets run first twice, and second once for each first result, for a total of four workers:
        wg.Add(4)
        go first(ch, wg)
        go first(ch, wg)
        // don't wait before starting the seconds
        go second(ch, wg)
        go second(ch, wg)
        wg.Wait()
    
        fmt.Println("All done")
    }
    

    Which outputs:

    Wait for a value from first
    Starting a first
    Starting a first
    Wait for a value from first
    Done with a first
    Starting a second with val 5577006791947779410
    Done with a first
    Starting a second with val 8674665223082153551
    Done with a second
    Done with a second
    All done
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 delphi webbrowser组件网页下拉菜单自动选择问题
  • ¥15 wpf界面一直接收PLC给过来的信号,导致UI界面操作起来会卡顿
  • ¥15 init i2c:2 freq:100000[MAIXPY]: find ov2640[MAIXPY]: find ov sensor是main文件哪里有问题吗
  • ¥15 运动想象脑电信号数据集.vhdr
  • ¥15 三因素重复测量数据R语句编写,不存在交互作用
  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了