在写入频道时,Defer从未打过电话

时间:2017-05-02 19:16:55

标签: go

我试图在goroutine函数中写入一个频道作为最后一个动作。

不幸的是,这不起作用。而waitGroup永远不会完成。

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。

1 个答案:

答案 0 :(得分:1)

问题是我只是写信道。永远不要读它。 如果不这样做,频道将毫无用处。

解决方法是:

在启动goroutines的循环之后从通道读取:

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