我可以使用make(chan someStruct)吗?

时间:2017-06-11 05:00:02

标签: go struct deadlock channel goroutine

例如:

type name struct {
    name string
    age int
}

func main() {
      c := make(chan name)

      c <- name{"sfsaf", 1}
      a, b := <- c

      close(c)
}

结果:

  

致命错误:所有goroutine都睡着了 - 死锁!

我想通过频道传递值。我该怎么办?

1 个答案:

答案 0 :(得分:7)

是的,你可以传递结构。但这不是你的OP中的问题。

当没有接收器准备接收时,您在通道上发送了一个值。这就是导致你陷入僵局的原因。

频道希望receiver被阻止,等待sender。这是通过Goroutines完成的。

因此,请将您的发件人包裹在goroutine中,这将不会立即执行。

package main

import (
    "fmt"
)

type name struct {
    name string
    age  int
}

func main() {
    c := make(chan name)

    go func() {
        c <- name{"sfsaf", 1}
        close(c)
    }()

    for n := range c {
        fmt.Println(n)
    }

    fmt.Println("channel was closed (all done!).")
}

在操场上看到它:https://play.golang.org/p/uaSuCaB4Ms

这是有效的,因为发件人的goroutine尚未执行。直到当前的goroutine执行被阻止。

我们在for n := range c循环中被阻止了。这是接收器,坐着等待价值观。 (这是一种常见的模式,使用for循环迭代通道值,因为它将坐下并阻塞,等待值。)

现在我们被阻止等待接收for循环中的值,现在将执行内联gorouting,以便在频道上发送我们的值。

此外,我们遵循安全做法,并在我们自己和close(c)频道后进行整理,发出for循环或select声明,表示不再发送任何值。 发件人总是关闭,而不是收件人 。这是for范围循环用于退出for循环的模式,并继续执行其余代码。

作为旁注,你通过传递struct的值来做得很好 - 而不是指针。

如果你传递了一个指针,你必须在对象周围实现一些互斥锁,以防止R / W恐慌。

Do not communicate by sharing memory; instead, share memory by communicating.

坚持在你的频道和goroutines周围传递价值而不是指针,并获得好处。