亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在Go中將通道中的值收集到切片中?

如何在Go中將通道中的值收集到切片中?

鳳凰求蠱 2022-09-12 16:28:14
假設我有一個幫助器函數,它返回一段可變長度的整數。我想并行運行各種值,并將輸出收集在一個大切片中。我的第一次嘗試如下:helper(n int)helper(n)npackage mainimport (    "fmt"    "golang.org/x/sync/errgroup")func main() {    out := make([]int, 0)    ch := make(chan int)    go func() {        for i := range ch {            out = append(out, i)        }    }()    g := new(errgroup.Group)    for n := 2; n <= 3; n++ {        n := n        g.Go(func() error {            for _, i := range helper(n) {                ch <- i            }            return nil        })    }    if err := g.Wait(); err != nil {        panic(err)    }    close(ch)    // time.Sleep(time.Second)    fmt.Println(out) // should have the same elements as [0 1 0 1 2]}func helper(n int) []int {    out := make([]int, 0)    for i := 0; i < n; i++ {        out = append(out, i)    }    return out}但是,如果我運行此示例,我不會獲得所有5個預期值,而是得到[0 1 0 1](如果我取消注釋,我確實得到了所有五個值,但這不是一個可接受的解決方案)。time.Sleep[0 1 2 0 1]似乎問題在于正在 goroutine 中更新,但函數在完成更新之前返回。outmain可行的一件事是使用大小為 5 的緩沖通道:func main() {    ch := make(chan int, 5)    g := new(errgroup.Group)    for n := 2; n <= 3; n++ {        n := n        g.Go(func() error {            for _, i := range helper(n) {                ch <- i            }            return nil        })    }    if err := g.Wait(); err != nil {        panic(err)    }    close(ch)    out := make([]int, 0)    for i := range ch {        out = append(out, i)    }    fmt.Println(out) // should have the same elements as [0 1 0 1 2]}但是,盡管在這個簡化的示例中我知道輸出的大小應該是多少,但在我的實際應用中,這先驗地不知道。從本質上講,我想要的是一個“無限”的緩沖區,這樣發送到通道永遠不會阻塞,或者是一種更習慣的方式來實現同樣的事情;我已經閱讀了 https://blog.golang.org/pipelines 但無法找到與我的用例非常匹配的內容。有什么想法嗎?
查看完整描述

1 回答

?
慕尼黑8549860

TA貢獻1818條經驗 獲得超11個贊

在此版本的代碼中,執行將被阻止,直到關閉。ch


ch始終在負責推送到 的例程結束時關閉。由于程序在例程中推送到,因此不需要使用緩沖通道。chch


package main


import (

    "fmt"


    "golang.org/x/sync/errgroup"

)


func main() {

    ch := make(chan int)


    go func() {

        g := new(errgroup.Group)

        for n := 2; n <= 3; n++ {

            n := n

            g.Go(func() error {

                for _, i := range helper(n) {

                    ch <- i

                }

                return nil

            })

        }

        if err := g.Wait(); err != nil {

            panic(err)

        }

        close(ch)

    }()


    out := make([]int, 0)

    for i := range ch {

        out = append(out, i)

    }


    fmt.Println(out) // should have the same elements as [0 1 0 1 2]

}


func helper(n int) []int {

    out := make([]int, 0)

    for i := 0; i < n; i++ {

        out = append(out, i)

    }

    return out

}

這是第一個代碼的固定版本,它很復雜,但演示了 的用法。sync.WaitGroup


package main


import (

    "fmt"

    "sync"


    "golang.org/x/sync/errgroup"

)


func main() {

    out := make([]int, 0)

    ch := make(chan int)


    var wg sync.WaitGroup

    wg.Add(1)

    go func() {

        defer wg.Done()

        for i := range ch {

            out = append(out, i)

        }

    }()


    g := new(errgroup.Group)

    for n := 2; n <= 3; n++ {

        n := n

        g.Go(func() error {

            for _, i := range helper(n) {

                ch <- i

            }

            return nil

        })

    }

    if err := g.Wait(); err != nil {

        panic(err)

    }

    close(ch)


    wg.Wait()

    // time.Sleep(time.Second)

    fmt.Println(out) // should have the same elements as [0 1 0 1 2]

}


func helper(n int) []int {

    out := make([]int, 0)

    for i := 0; i < n; i++ {

        out = append(out, i)

    }

    return out

}


查看完整回答
反對 回復 2022-09-12
  • 1 回答
  • 0 關注
  • 87 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號