Golang – 在结构体中使用 chan 切片

huangapple go评论85阅读模式
英文:

Golang - Using chan slice inside struct

问题

我正在尝试在结构体中使用一个切片通道类型,类似下面的代码。然而,当我尝试接收时:

test := <-c.slice

程序会挂起。有没有办法解决这个问题?

package main

import "fmt"

type blah struct {
    slice chan [][]int
}

func main() {

    slice := make([][]int, 3)
    c := blah{make(chan [][]int)}

    slice[0] = []int{1, 2, 3}
    slice[1] = []int{4, 5, 6}
    slice[2] = []int{7, 8, 9}

    go func() {
        test := <-c.slice
        test = slice
        c.slice <- test
    }()

    fmt.Println(<-c.slice)
}
英文:

I am trying to use a slice chan type inside a struct, similar to the code below.
However, when I try to receive at

test := &lt;-c.slice

The program hangs. Is there a way to do this?

package main

import &quot;fmt&quot;

type blah struct {
	slice chan [][]int
}

func main() {
	
	slice := make([][]int, 3)
	c := blah{make(chan [][]int)}

	slice[0] = []int{1, 2, 3}
	slice[1] = []int{4, 5, 6}
	slice[2] = []int{7, 8, 9}

	go func() {
		test := &lt;- c.slice
		test = slice
		c.slice &lt;- test
	}()

	fmt.Println(&lt;-c.slice)
}

答案1

得分: 11

在goroutine内部的第一行从通道接收数据,创建goroutine后,在main函数中的第一行也是从通道接收数据。这意味着系统中只有两个goroutine都在尝试从切片通道接收数据,而没有人尝试向其中发送数据。

更一般地说,问题在于要有人接收(消费),就必须有其他人同时发送(生产)。如果通道是有缓冲的,这在你的示例中并不是这样,发送也可能在同一个goroutine中提前发生。

所以这个例子可以工作,因为通道有一个元素的缓冲区,这意味着发送不会阻塞:

ch := make(chan int, 1)
ch <- 1
i := <-ch

这个例子也可以工作,因为发送与接收同时发生:

ch := make(chan int)
go func() { ch <- 1 }()
i := <-ch

这个例子不工作,因为两个goroutine都在尝试向无缓冲通道发送数据,而没有人尝试接收:

ch := make(chan int)
go func() { ch <- 1 }()
ch <- 2

这个例子也不工作,因为两个goroutine都在尝试接收数据,而没有人尝试发送:

ch := make(chan int)
go func() { <-ch }()
<-ch

最后一个例子就是你的情况。

英文:

The first line inside the goroutine receives from the channel, and so does the first line in main after the goroutine is created. That means the only two goroutines in the system are both trying to receive from the slice channel, and nobody is trying to send into it.

More generally, the issue is that for somebody to receive (consume), somebody else has to concurrently send (produce). If the channel was buffered, which isn't the case in your example, the send might also happen ahead of time in the same goroutine.

So this works, for example, because the channel has a buffer of one element, which means the send won't block:

ch := make(chan int, 1)
ch &lt;- 1
i := &lt;-ch

This works as well, because the send is happening concurrently with the receive:

ch := make(chan int)
go func() { ch &lt;- 1 }()
i := &lt;-ch

This does not work, because both goroutines are trying to send into an unbuffered channel, and nobody is trying to receive:

ch := make(chan int)
go func() { ch &lt;- 1 }()
ch &lt;- 2

This does not work either, because both goroutines are trying to receive, and nobody is trying to send:

ch := make(chan int)
go func() { &lt;-ch }()
&lt;-ch

That last one is your case.

huangapple
  • 本文由 发表于 2013年9月10日 10:51:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/18710010.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定