如何高效关闭通道?
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()
}
我希望这就是您要找的。
我正在尝试做一些事情:
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()
}
我希望这就是您要找的。