新手去。我正在尝试读取map[int][]string
,将片段写入中间通道,然后一旦写完所有内容,将所有字符串从中间通道读回另一个通道,最后将通道读入另一个goroutine。
我无法弄清楚什么是从中间通道读取的良好非阻塞方式。
package main
import (
"fmt"
)
func f1(c chan []string, q chan int) {
// intermediate channel
ic := make(chan []string, 10)
hmap := map[int][]string{
0: []string{"a", "b", "c"},
1: []string{"d", "e",},
2: []string{"f", "g", "h"},
}
// for every elem in hmap put the values into intermediate channel
for _, v := range hmap {
f2(v, ic)
}
// everything is in intermediate channel by now
// read all the []string and concatenate them into a slice in a
// non-blocking fashion
var strs []string
for v := range ic {
strs = append(strs, v...)
}
// strs := <-ic
fmt.Println(strs)
select {
case c <- strs:
fmt.Println("Received strings.")
default:
fmt.Println("did not receive anything.")
}
q <- 1
}
func f2(v []string, ic chan []string) {
select {
case ic <- v:
fmt.Println("Sent to intermediate channel:", v)
default:
fmt.Println("nothing to send...")
}
}
func f3(c chan []string) {
fmt.Println(<-c)
}
func main() {
c := make(chan []string, 10)
q := make(chan int)
go f1(c, q)
go f3(c)
fmt.Println(<-q) // to wait for the quit to be set
}
go run main.go
要运行。
这个程序陷入僵局。我怎样才能避免死锁?
答案 0 :(得分:1)
正如@zerkms在评论中所说,你需要在写完频道时关闭频道,否则for v := range ic {
会阻止。
package main
import (
"fmt"
)
func f1(c chan []string, q chan int) {
ic := make(chan []string, 10)
hmap := map[int][]string{
0: []string{"a", "b", "c"},
1: []string{"d", "e"},
2: []string{"f", "g", "h"},
}
for _, v := range hmap {
f2(v, ic)
}
// done writing strings, close the channel
close(ic)
var strs []string
for v := range ic {
strs = append(strs, v...)
}
fmt.Println(strs)
select {
case c <- strs:
fmt.Println("Received strings.")
default:
fmt.Println("did not receive anything.")
}
q <- 1
}
func f2(v []string, ic chan []string) {
select {
case ic <- v:
fmt.Println("Sent to intermediate channel:", v)
default:
fmt.Println("nothing to send...")
}
}
func f3(c chan []string) {
fmt.Println(<-c)
}
func main() {
c := make(chan []string, 10)
q := make(chan int)
go f1(c, q)
go f3(c)
fmt.Println(<-q) // to wait for the quit to be set
}