英文:
Multiple concurrency in golang
问题
我正在尝试将一个简单的同步 PHP 代码转换为 Go,但是在理解并发与通道的工作原理方面遇到了困难。PHP 脚本首先发送请求以获取媒体库部分的列表,然后发送请求以获取每个部分中的项目。如果该部分是电视节目列表,则会发送请求以获取所有季节,并发送另一个请求以获取每个季节中的剧集。
我尝试使用 Go 编写了一个我认为可以工作的 pidgeon-go 版本,但是没有成功。我尝试了一些在线的通道指南,但通常会出现死锁警告。目前,这个示例会警告 "item := <-ch" 用作值,并且似乎没有等待 goroutine 返回的样子。有人有任何想法我该怎么做吗?
package main
import (
"fmt"
"time"
)
// 获取所有部分的所有项目
func main() {
ch := make(chan string)
sections := getSections()
for _, section := range sections {
go getItemsInSection(section, ch)
}
items := make([]string, 0)
for item := range ch {
items = append(items, item)
}
fmt.Println(items)
}
// 返回各个库部分的列表
func getSections() []string {
return []string{"高清电影", "电影", "电视节目"}
}
// 获取给定部分中的项目,注意某些项目可能会生成子项目
func getItemsInSection(name string, ch chan string) {
time.Sleep(1 * time.Second)
switch name {
case "高清电影":
ch <- "阿凡达"
ch <- "复仇者联盟"
case "电影":
ch <- "异形"
ch <- "深渊"
case "电视节目":
go getSubItemsForItem("24", ch)
go getSubItemsForItem("绝命毒师", ch)
}
}
// 获取给定父项的子项目
func getSubItemsForItem(name string, ch chan string) {
time.Sleep(1 * time.Second)
ch <- name + ": S01E01"
ch <- name + ": S01E02"
}
希望对你有帮助!
英文:
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?
package main
import (
"fmt"
"time"
)
// Get all items for all sections
func main() {
ch := make(chan string)
sections := getSections()
for _, section := range sections {
go getItemsInSection(section, ch)
}
items := make([]string, 0)
for item := <- ch {
items = append(items, item)
}
fmt.Println(items)
}
// Return a list of the various library sections
func getSections() []string {
return []string{"HD Movies", "Movies", "TV Shows"}
}
// Get items within the given section, note that some items may spawn sub-items
func getItemsInSection(name string, ch chan string) {
time.Sleep(1 * time.Second)
switch name {
case "HD Movies":
ch <- "Avatar"
ch <- "Avengers"
case "Movies":
ch <- "Aliens"
ch <- "Abyss"
case "TV Shows":
go getSubItemsForItem("24", ch)
go getSubItemsForItem("Breaking Bad", ch)
}
}
// Get sub-items for a given parent
func getSubItemsForItem(name string, ch chan string) {
time.Sleep(1 * time.Second)
ch <- name + ": S01E01"
ch <- name + ": S01E02"
}
答案1
得分: 2
首先,该代码无法编译,因为for item := <- ch
应该是for item := range ch
。
现在的问题是你要么需要关闭通道,要么在goroutine中无限循环运行你的循环。
go func() {
for {
item, ok := <-ch
if !ok {
break
}
fmt.Println(item)
items = append(items, item)
}
}()
time.Sleep(time.Second)
fmt.Println(items)
英文:
First, that code doesn't compile because for item := <- 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.
go func() {
for {
item, ok := <-ch
if !ok {
break
}
fmt.Println(item)
items = append(items, item)
}
}()
time.Sleep(time.Second)
fmt.Println(items)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论