多个 goroutine 有选择地在一个通道上监听

sub*_*ker 1 channel go goroutine

我已经看过这个这个这个这个,但在这种情况下没有一个真正帮助我。如果通道中的值是针对该特定 goroutine 的,我有多个 goroutine 需要执行某些任务。

var uuidChan chan string

func handleEntity(entityUuid string) {
    go func() {
        for {
            select {
            case uuid := <-uuidChan:
                if uuid == entityUuid {
                    // logic
                    println(uuid)
                    return
                }
            case <-time.After(time.Second * 5):
                println("Timeout")
                return
            }
        }
    }()
}

func main() {
    uuidChan = make(chan (string))
    for i := 0; i < 5; i++ {
        handleEntity(fmt.Sprintf("%d", i))
    }
    for i := 0; i < 4; i++ {
        uuidChan <- fmt.Sprintf("%d", i)
    }
}
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/Pu5MhSP9Qtj

在上述逻辑中,uuid 被其中一个通道接收,并且什么也没有发生。为了解决这个问题,如果某些 uuid 的逻辑不在该例程中,我尝试更改逻辑以将 uuid 重新插入通道。我知道这是一种不好的做法,而且也行不通。

func handleEntity(entityUuid string) {
    go func() {
        var notMe []string // stores list of uuids that can't be handled by this routine and re-inserts it in channel.
        for {
            select {
            case uuid := <-uuidChan:
                if uuid == entityUuid {
                    // logic
                    println(uuid)
                    return
                } else {
                    notMe = append(notMe, uuid)
                }
            case <-time.After(time.Second * 5):
                println("Timeout")
                defer func() {
                    for _, uuid := range notMe {
                        uuidChan <- uuid
                    }
                }()
                return
            }
        }
    }()
}
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/5On-Vd7UzqP

这样做的正确方法是什么?

小智 5

也许您想映射您的频道以立即将消息发送到正确的 goroutine:

package main

import (
    "fmt"
    "time"
)

func worker(u string, c chan string) {
    for {
        fmt.Printf("got %s in %s\n", <-c, u)
    }
}

func main() {
    workers := make(map[string]chan string)

    for _, u := range []string{"foo", "bar", "baz"} {
        workers[u] = make(chan string)
        go worker(u, workers[u])
    }

    workers["foo"] <- "hello"
    workers["bar"] <- "world"
    workers["baz"] <- "!"

    fmt.Println()

    time.Sleep(time.Second)
}
Run Code Online (Sandbox Code Playgroud)