英文:
How can I use channel send direction in Go
问题
在Go语言中,可以指定通道的发送方向。我正在尝试创建一个相关示例,请看下面的代码:
package main
import (
"fmt"
"time"
)
func main() {
ic_send_only := make(<-chan int) // 只能发送数据的通道 - 箭头指向外部表示发送
ic_recv_only := make(chan<- int) // 只能接收数据的通道 - 箭头指向内部表示接收
go func() {
ic_recv_only <- 4555
}()
go func() {
ic_send_only <- ic_recv_only
}()
fmt.Println(ic_recv_only)
time.Sleep(10000)
}
我得到了编译器错误:
# command-line-arguments
.\send_receive.go:19: invalid operation: ic_send_only <- ic_recv_only (send to receive-only type <-chan int)
[Finished in 0.2s with exit code 2]
我应该如何正确使用通道方向?
还是有其他人有比我更好的示例吗?
英文:
In Go, it can be specified which direction a channel can send. I am trying to create an example about it, look at the following code:
package main
import (
"fmt"
"time"
)
func main() {
ic_send_only := make(<-chan int) //a channel that can only send data - arrow going out is sending
ic_recv_only := make(chan<- int) //a channel that can only receive a data - arrow going in is receiving
go func() {
ic_recv_only <- 4555
}()
go func() {
ic_send_only <- ic_recv_only
}()
fmt.Println(ic_recv_only)
time.Sleep(10000)
}
I get the compiler error
# command-line-arguments
.\send_receive.go:19: invalid operation: ic_send_only <- ic_recv_only (send to receive-only type <-chan int)
[Finished in 0.2s with exit code 2]
How can I use channel direction in the right way?
Or does anyone have a better sample than me?
答案1
得分: 27
三个问题:
- 你把发送和接收操作颠倒了(这就是你看到的错误)
- 创建只接收或只发送的通道没有意义,因为你不能使用它们
- 你使用的符号尝试发送通道本身,而不是结果。你需要接收 并且 发送,这需要两个箭头。
ic_recv_only <- <-ic_send_only
你可能会因为术语颠倒而感到困惑。<-ch
是一个“接收操作”,而 ch <-
是一个发送操作。请注意,在你的示例中,由于你无法完成相应的发送和接收来通过任何一个通道传递数据,所以一切都会陷入僵局。
这是一个完整的示例:
// 这从通道接收一个整数。通道是只接收的
func consumer(ch <-chan int) int {
return <-ch
}
// 这通过通道发送一个整数。通道是只发送的
func producer(i int, ch chan<- int) {
ch <- i
}
func main() {
ch := make(chan int)
go producer(42, ch)
result := consumer(ch)
fmt.Println("received", result)
}
英文:
Three issues:
-
You have the send and receive operations reversed (which is the error you're seeing)
-
Creating recv-only or send-only channels make no sense, as you cannot use them
-
The notation you're using is trying to send the channel itself, not the result. You need to receive and send, which requires two arrows.
ic_recv_only <- <-ic_send_only
You may be confused because you have the terminology reversed. <-ch
is a "receive operation", and ch <-
is a send operation. Note that in your example, everything would be deadlocked because you can't complete the corresponding sends and receives to pass something through either channel.
Here is a complete example:
// This receives an int from a channel. The channel is receive-only
func consumer(ch <-chan int) int {
return <-ch
}
// This sends an int over a channel. The channel is send-only
func producer(i int, ch chan<- int) {
ch <- i
}
func main() {
ch := make(chan int)
go producer(42, ch)
result := consumer(ch)
fmt.Println("received", result)
}
答案2
得分: 1
JimB所提出的关键点总结如下:
- 使用
make
创建通道。 - 每个通道都有两个端点。
- 通过通道的端点进行通信,使用
<-
操作符。端点非常重要。 - 通道有一个发送端和一个接收端,通道是单向的。
还要注意,每个端点可以被多个goroutine同时安全地访问。
此外,还要注意JimB的示例中,producer(i int, ch chan<- int)
和consumer(ch <-chan int)
函数的参数通过<-chan
和chan<-
指定了它们使用的端点,而不仅仅是chan
。虽然这是可选的,但这是良好的实践,因为如果你这样做,编译器将帮助你修复愚蠢的错误。
英文:
The key point that JimB has made, to summarise, is that
- You create channels using
make
- Every channel has two ends.
- You communicate via the ends of channels via
<-
. The ends are important. - There is a sending end and a receiving end; channels are unidirectional.
Note also that each end can be safely accessed concurrently by more than one goroutine.
Also note that JimB's example producer(i int, ch chan<- int)
and consumer(ch <-chan int)
functions have parameters that specify which end they use via <-chan
and chan<-
, instead of just chan
. Although this is optional, it is good practice because the compiler will help you fix silly mistakes if you do this.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论