Golang中的多并发

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

Multiple concurrency in golang

问题

我正在尝试将一个简单的同步 PHP 代码转换为 Go,但是在理解并发与通道的工作原理方面遇到了困难。PHP 脚本首先发送请求以获取媒体库部分的列表,然后发送请求以获取每个部分中的项目。如果该部分是电视节目列表,则会发送请求以获取所有季节,并发送另一个请求以获取每个季节中的剧集。

我尝试使用 Go 编写了一个我认为可以工作的 pidgeon-go 版本,但是没有成功。我尝试了一些在线的通道指南,但通常会出现死锁警告。目前,这个示例会警告 "item := <-ch" 用作值,并且似乎没有等待 goroutine 返回的样子。有人有任何想法我该怎么做吗?

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. // 获取所有部分的所有项目
  7. func main() {
  8. ch := make(chan string)
  9. sections := getSections()
  10. for _, section := range sections {
  11. go getItemsInSection(section, ch)
  12. }
  13. items := make([]string, 0)
  14. for item := range ch {
  15. items = append(items, item)
  16. }
  17. fmt.Println(items)
  18. }
  19. // 返回各个库部分的列表
  20. func getSections() []string {
  21. return []string{"高清电影", "电影", "电视节目"}
  22. }
  23. // 获取给定部分中的项目,注意某些项目可能会生成子项目
  24. func getItemsInSection(name string, ch chan string) {
  25. time.Sleep(1 * time.Second)
  26. switch name {
  27. case "高清电影":
  28. ch <- "阿凡达"
  29. ch <- "复仇者联盟"
  30. case "电影":
  31. ch <- "异形"
  32. ch <- "深渊"
  33. case "电视节目":
  34. go getSubItemsForItem("24", ch)
  35. go getSubItemsForItem("绝命毒师", ch)
  36. }
  37. }
  38. // 获取给定父项的子项目
  39. func getSubItemsForItem(name string, ch chan string) {
  40. time.Sleep(1 * time.Second)
  41. ch <- name + ": S01E01"
  42. ch <- name + ": S01E02"
  43. }

希望对你有帮助!

英文:

I'm trying to port a simple synchronous bit of PHP to Go, but am having a hard time getting my head around how concurrency works with regards to channels. The PHP script makes a request to get a list of media library sections, then makes requests to get the items within each of these sections. If the section is a list of TV Shows, it then makes a request for each show to get all the seasons and then another to get the episodes within each season.

I've trying writing in pidgeon-go what I expected to work, but I'm not having any luck. I've tried various channel guides online, but normally end up with deadlock warnings. Currently this example warns about item := <-ch used as value and doesn't look like it's waiting on the goroutines to return. Does anyone have any ideas what I can do?

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;time&quot;
  5. )
  6. // Get all items for all sections
  7. func main() {
  8. ch := make(chan string)
  9. sections := getSections()
  10. for _, section := range sections {
  11. go getItemsInSection(section, ch)
  12. }
  13. items := make([]string, 0)
  14. for item := &lt;- ch {
  15. items = append(items, item)
  16. }
  17. fmt.Println(items)
  18. }
  19. // Return a list of the various library sections
  20. func getSections() []string {
  21. return []string{&quot;HD Movies&quot;, &quot;Movies&quot;, &quot;TV Shows&quot;}
  22. }
  23. // Get items within the given section, note that some items may spawn sub-items
  24. func getItemsInSection(name string, ch chan string) {
  25. time.Sleep(1 * time.Second)
  26. switch name {
  27. case &quot;HD Movies&quot;:
  28. ch &lt;- &quot;Avatar&quot;
  29. ch &lt;- &quot;Avengers&quot;
  30. case &quot;Movies&quot;:
  31. ch &lt;- &quot;Aliens&quot;
  32. ch &lt;- &quot;Abyss&quot;
  33. case &quot;TV Shows&quot;:
  34. go getSubItemsForItem(&quot;24&quot;, ch)
  35. go getSubItemsForItem(&quot;Breaking Bad&quot;, ch)
  36. }
  37. }
  38. // Get sub-items for a given parent
  39. func getSubItemsForItem(name string, ch chan string) {
  40. time.Sleep(1 * time.Second)
  41. ch &lt;- name + &quot;: S01E01&quot;
  42. ch &lt;- name + &quot;: S01E02&quot;
  43. }

答案1

得分: 2

首先,该代码无法编译,因为for item := &lt;- ch应该是for item := range ch

现在的问题是你要么需要关闭通道,要么在goroutine中无限循环运行你的循环。

  1. go func() {
  2. for {
  3. item, ok := <-ch
  4. if !ok {
  5. break
  6. }
  7. fmt.Println(item)
  8. items = append(items, item)
  9. }
  10. }()
  11. time.Sleep(time.Second)
  12. fmt.Println(items)

<kbd>playground</kbd>

英文:

First, that code doesn't compile because for item := &lt;- ch should be for item := range ch

Now the problem is you either have to close the channel or run your loop forever inside a goroutine.

  1. go func() {
  2. for {
  3. item, ok := &lt;-ch
  4. if !ok {
  5. break
  6. }
  7. fmt.Println(item)
  8. items = append(items, item)
  9. }
  10. }()
  11. time.Sleep(time.Second)
  12. fmt.Println(items)

<kbd>playground</kbd>

huangapple
  • 本文由 发表于 2014年8月17日 23:59:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/25350945.html
匿名

发表评论

匿名网友

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

确定