小编典典

如何有效关闭渠道?

go

我正在尝试做一些事情:

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例程的这种方式正确吗?


阅读 363

收藏
2020-07-02

共1个答案

小编典典

这是生产者-
消费者类型的示例。我只使用WaitGrouphere,这样主goroutine不会立即退出。从理论上讲,您的应用程序可以等待,或者在此期间做一些其他有趣的事情。

请注意,您还可以使用c := make(chan(*Feed, n))其中n要缓冲编号的缓冲通道。请注意,在典型的生产者-
消费者方案中,有时每个作业分配了很多资源。因此,根据需要,您可以仅缓冲其中的一些缓冲,也可以全部缓冲。

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

编辑 我在打印“开始”之前添加了一个暂停,以使输出不太同步。以前总是输出:

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()
}

我希望这是您想要的。

2020-07-02