如何通过go例程连接多个切片

时间:2018-05-22 00:48:01

标签: go

新手去。我正在尝试读取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要运行。

这个程序陷入僵局。我怎样才能避免死锁?

1 个答案:

答案 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
}

https://play.golang.org/p/qZoAElTlkAa