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

如何让 Go channel worker 有不同的结果长度?

如何让 Go channel worker 有不同的结果长度?

Go
撒科打诨 2023-01-03 15:47:04
我从gobyexample做了一些编辑:import (    "fmt"    "math/rand"    "time")type DemoResult struct {    Name string    Rate int}func random(min, max int) int {    rand.Seed(time.Now().UTC().UnixNano())    return rand.Intn(max-min) + min}func worker(id int, jobs <-chan int, results chan<- DemoResult) {    for j := range jobs {        fmt.Println("worker", id, "started  job", j)        time.Sleep(time.Second)        fmt.Println("worker", id, "finished job", j)        myrand := random(1, 4)        if myrand == 2 {            results <- DemoResult{Name: "succ", Rate: j}        }        //  else {        //  results <- DemoResult{Name: "failed", Rate: 999}        // }    }}func main() {    const numJobs = 5    jobs := make(chan int, numJobs)    results := make(chan DemoResult)    for w := 1; w <= 3; w++ {        go worker(w, jobs, results)    }    for j := 1; j <= numJobs; j++ {        jobs <- j    }    close(jobs)    for a := 1; a <= numJobs; a++ {        out := <-results        if out.Name == "succ" {            fmt.Printf("%v\n", out)        }    }}我评论了以下代码,故意让它永远卡住:        //  else {        //  results <- DemoResult{Name: "failed", Rate: 999}        // }看起来我们应该使结果的长度与作业的长度相同。我想知道我们是否可以让它有不同的长度?
查看完整描述

2 回答

?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

使用等待组来检测工作人员何时完成。工作人员完成后关闭结果通道。接收结果直到通道关闭。

func worker(wg *sync.WaitGroup, id int, 

            jobs <-chan int, 

            results chan<- DemoResult) {

    // Decrement wait group counter on return from

    // function.

    defer wg.Done()

    ⋮ 

}



func main() {

    ⋮

    // Declare wait group and increment counter for

    // each worker.

    var wg sync.WaitGroup

    for w := 1; w <= 3; w++ {

        wg.Add(1)

        go worker(&wg, w, jobs, results)

    }

    ⋮

    // Wait for workers to decrement wait group

    // counter to zero and close channel.

    // Execute in goroutine so we can continue on 

    // to receiving values from results in main. 

    go func() {

        wg.Wait()

        close(results)

    }()

    ⋮

    // Loop until results is closed.

    for out := range results {

       ⋮

    }

}

https://go.dev/play/p/FOQwybMl7tM


查看完整回答
反对 回复 2023-01-03
?
慕虎7371278

TA贡献1802条经验 获得超4个赞

我想知道我们是否可以让它有不同的长度?

绝对可以,但是您需要某种方法来确定何时到达结果的末尾。这就是您的示例失败的原因 - 目前该函数假设会有numJobs(每个作业一个结果)结果并等待那么多。

另一种方法是使用通道关闭来指示这一点,即(游乐场

package main


import (

    "fmt"

    "math/rand"

    "sync"

    "time"

)


type DemoResult struct {

    Name string

    Rate int

}


func random(min, max int) int {

    rand.Seed(time.Now().UTC().UnixNano())

    return rand.Intn(max-min) + min

}


func worker(id int, jobs <-chan int, results chan<- DemoResult) {

    for j := range jobs {

        fmt.Println("worker", id, "started  job", j)

        time.Sleep(time.Second)

        fmt.Println("worker", id, "finished job", j)

        myrand := random(1, 4)

        if myrand == 2 {

            results <- DemoResult{Name: "succ", Rate: j}

        } // else {

        //  results <- DemoResult{Name: "failed", Rate: 999}

        //}

    }

}


func main() {

    const numWorkers = 3

    const numJobs = 5

    jobs := make(chan int, numJobs)

    results := make(chan DemoResult)


    var wg sync.WaitGroup

    wg.Add(numWorkers)

    for w := 1; w <= numWorkers; w++ {

        go func() {

            worker(w, jobs, results)

            wg.Done()

        }()

    }

    go func() {

        wg.Wait() // Wait for go routines to complete then close results channel

        close(results)

    }()


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

        jobs <- j

    }

    close(jobs)


    for out := range results {

        if out.Name == "succ" {

            fmt.Printf("%v\n", out)

        }

    }

}


查看完整回答
反对 回复 2023-01-03
  • 2 回答
  • 0 关注
  • 71 浏览
慕课专栏
更多

添加回答

举报

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