go - 如何通过go例程连接多个 slice

标签 go

新的去。我正在尝试读取 map[int][]string,将字符串 slice 写入中间 channel ,然后在写入所有内容后,将所有字符串从中间 channel 读回另一个 channel ,最后将 channel 读入另一个 goroutine。

我无法弄清楚什么是从中间 channel 读取的良好非阻塞方式。

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 运行。

这个程序进入死锁状态。如何避免死锁?

最佳答案

正如@zerkms 在评论中所说,您需要在完成写入后关闭 channel ,否则 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

关于go - 如何通过go例程连接多个 slice ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50458313/

相关文章:

docker - 无法安装 golint 包 : wrong import path

go - 如何将记录器中间件输出数据传递到golang中的mysql表中?

go - 内存有效的方式

go - 服务器端 oauth : What to do with the tokens received

java - 为什么 Go 这么慢(与 Java 相比)?

xml - 在 Go 中解析 XML

url - 为什么 url.Parse 不填充 URL.RawPath?

function - Go 中函数类型有什么用途?

go - 并发读取文件的最佳方式

戈朗 : how to cast []string to a typed struct?