如何高效关闭通道?

How to efficiently close the channel?

我正在尝试做一些事情:

type Feed struct {
    title, descr, link string
    published          time.Time
}
func main() {
    ar := make([]Feed, 0)
    for i := 0; i < 3; i++ {
        f: = new(Feed)
        // do some stuff with feed
        ar = append(ar, *f)
    }

    ch := make(chan Feed, 3)

    for _, i := range ar {
        go process(i, ch)
    }

    r :=0
    for i := range ch {
        fmt.Println(i)
        r++
        if r == 3 {
            close(ch)
        }
    }
}
func process(i Feed, ch chan Feed) {
 // do some stuff
 ch <- i
}

看来ar是不必要的,但如果去掉,最后的范围就永远了。我做错了什么?

另一个问题是 - 这种使用 Go 例程的方式是否正确?

这是一个生产者-消费者类型的例子。我在这里只使用 WaitGroup 这样主 goroutine 就不会立即退出。理论上你的应用程序可以等待,或者同时做一些其他有趣的事情。

请注意,您还可以使用 c := make(chan(*Feed, n)) 来使用缓冲通道,其中 n 是您要缓冲的数字。请注意,在典型的生产者-消费者场景中,有时每个作业会分配大量资源。因此,根据您的需要,您可以只缓冲一些,或者全部缓冲。

没有缓冲通道,它充当 goroutine 之间的同步。生产者阻塞在 c <- 等待消费者的 <- c 移交,因此每个例程中一次只有一个执行这些行。

EDIT 我在打印前添加了一个暂停 "started" 以使输出不太同步。它以前总是输出:

created
started
created
started
...

https://play.golang.org/p/FmWqegr-CR

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

type Feed struct {
    title, descr, link string
    published          time.Time
}

func CreateFeed() *Feed {
    r := rand.Int() % 500
    time.Sleep(1000 + time.Duration(r)*time.Millisecond)
    fmt.Println("Feed created")
    return &Feed{
        published: time.Now(),
    }
}

func UseFeed(f *Feed) {
    time.Sleep(100 * time.Millisecond)
    fmt.Println("Feed started")
    time.Sleep(1600 * time.Millisecond)
    fmt.Printf("Feed consumed: %s\n", f.published)
}

func main() {
    numFeeds := 10

    var wg sync.WaitGroup
    wg.Add(10)

    c := make(chan (*Feed))
    for i := 0; i < numFeeds; i++ {
        go func() { c <- CreateFeed() }()
    }

    for i := 0; i < numFeeds; i++ {
        go func() {
            f := <-c
            UseFeed(f)
            wg.Done()
        }()
    }

    wg.Wait()
}

我希望这就是您要找的。