当向通道写入数据时,永远不会调用”defer”。

huangapple go评论88阅读模式
英文:

Defer never called when writing to channel

问题

我正在尝试在goroutine函数的最后一个操作中向通道写入数据。

不幸的是,这并没有起作用,而且等待组永远不会完成。

import (
    "sync"
    "github.com/SlyMarbo/rss"
    "fmt"
)

func main() {
    urls := []string{"http://rss.cnn.com/rss/edition.rss", "http://rss.time.com/web/time/rss/top/index.xml"}

    var c = make(chan string)
    var wg sync.WaitGroup
    for _, url := range urls {
        wg.Add(1)
        go receiveRss(url, &wg, c)
    }
    wg.Wait()
    fmt.Println("==============DONE=================")
}

func receiveRss(url string, wg *sync.WaitGroup, c chan string) {
    defer wg.Done()
    feed, err := rss.Fetch(url)
    if err != nil {
        fmt.Println("Failed to retrieve RSS feed", err)
    }

    items := feed.Items
    for _, item := range items {
        c <- item.Title
    }
}

当将c <- item.Title替换为fmt.Println(item.Title)时,延迟函数被调用并打印出"DONE"。

英文:

I'm trying to write to a channel as last action in a goroutine function.

Unfortunately this is not working. And the waitGroup is never done.

import (
    &quot;sync&quot;
	&quot;github.com/SlyMarbo/rss&quot;
    &quot;fmt&quot;
)

func main() {
	urls := []string{&quot;http://rss.cnn.com/rss/edition.rss&quot;, &quot;http://rss.time.com/web/time/rss/top/index.xml&quot;}

	var c = make(chan string)
    var wg sync.WaitGroup
	for _, url := range urls {
		wg.Add(1)
    	go receiveRss(url, &amp;wg, c)
	}
    wg.Wait()
	fmt.Println(&quot;==============DONE=================&quot;)
}

func receiveRss(url string, wg *sync.WaitGroup, c chan string) {
	defer wg.Done()
    feed, err := rss.Fetch(url)
	if err != nil {
    	fmt.Println(&quot;Failed to retrieve RSS feed&quot;, err)
	}

    items := feed.Items
	for _, item := range items {
    	c &lt;- item.Title
	}
}

When replacing c &lt;- item.Title with fmt.Println(item.Title) the deferred function is called and DONE is printed.

答案1

得分: 1

问题是我只是向通道写入数据,从未从中读取数据。
如果不这样做,通道将是无用的。

解决方法是:

在启动goroutine的循环之后从通道中读取数据:

for title := range c {
	fmt.Println(title)
}

这会导致无限循环,如果通道从未关闭。
所以我在写入数据后关闭通道:

close(c)

以下是完整的代码:

func main() {

	urls := []string{"http://rss.cnn.com/rss/edition.rss", "http://rss.time.com/web/time/rss/top/index.xml"}

	var c = make(chan []string)
	var wg sync.WaitGroup

	for _, url := range urls {
		wg.Add(1)
		go receiveRss(url, &wg, c)
	}
	for title := range c {
		fmt.Println(title)
	}
	wg.Wait()
	fmt.Println("==============DONE=================")
}

func receiveRss(url string, wg *sync.WaitGroup, c chan []string) {
	defer wg.Done()
	feed, err := rss.Fetch(url)
	if err != nil {
		fmt.Println("Failed to retrieve RSS feed", err)
	}

	items := feed.Items
	var titles []string
	for _, item := range items {
		titles = append(titles, item.Title)
	}
	c <- titles
	close(c)
}
英文:

The problem is that I was only writing to the channel. Never reading from it.
Without doing this the channel would be useless.

The solution to this is:

Reading from the channel after the loop which starts the goroutines:

for title := range c {
	fmt.Println(title)
}

This then causes an endless loop if the channel is never closed.
So I just close the channel after writing to it:

close(c)

Here is the whole code:

func main() {

	urls := []string{&quot;http://rss.cnn.com/rss/edition.rss&quot;, &quot;http://rss.time.com/web/time/rss/top/index.xml&quot;}

	var c = make(chan []string)
	var wg sync.WaitGroup

	for _, url := range urls {
		wg.Add(1)
		go receiveRss(url, &amp;wg, c)
	}
	for title := range c {
		fmt.Println(title)
	}
	wg.Wait()
	fmt.Println(&quot;==============DONE=================&quot;)
}

func receiveRss(url string, wg *sync.WaitGroup, c chan []string) {
	defer wg.Done()
	feed, err := rss.Fetch(url)
	if err != nil {
		fmt.Println(&quot;Failed to retrieve RSS feed&quot;, err)
	}

	items := feed.Items
	var titles []string
	for _, item := range items {
		titles = append(titles, item.Title)
	}
	c &lt;- titles
	close(c)
}

huangapple
  • 本文由 发表于 2017年5月3日 03:16:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/43745595.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定