我正在努力了解Go的频道。我想我理解一个基本的双向chan
但我对理解<-chan
和chan<-
的态度不足。
我希望它们对于以某种方式与线程进行通信非常有用,但我遇到了实际读取和接收该值的线程问题。
package main
import (
"fmt"
"time"
)
func Thread(c chan<- int) {
for {
num := <-c
fmt.Println("Thread : ", num)
time.Sleep(time.Second)
}
}
func main() {
c := make(chan<- int, 3)
go Thread(c)
for i := 1; i <= 10; i++ {
c <- i
}
for len(c) > 0 {
time.Sleep(100)
}
}
我尝试在<-chan
中使用chan<-
代替make()
,但同样的事情发生了:
C:\>go run chan.go
# command-line-arguments
.\chan.go:10: invalid operation: <-c (receive from send-only type chan<- int)
如果我无法从频道阅读,为什么还要写信呢?考虑到这一点,我认为我必须做错事。我期望仅发送chan
意味着一个线程只能发送而另一个线程只能接收。情况似乎并非如此。
如果我完全删除<-
,它会起作用,但这会使它成为双向的,允许go例程响应(即使它从未这样做),我希望避免这种情况。似乎我可以将数字驱逐到我永远无法读取的chan
,或者我可以从chan
中读取不可能写入的数字。
我希望做的是将主线程中的整数发送到go例程,以便使用单向通道进行打印。我做错了什么?
如果重要的话,这是在Windows上使用1.3.3。更新到1.4没有帮助。我可能想提一下这也是x64。
答案 0 :(得分:4)
The Go Programming Language Specification
通道提供了一种同时执行函数的机制 通过发送和接收指定元素的值进行通信 类型。未初始化频道的值为零。
ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
可选&lt; - 运算符指定通道方向,发送或 接收。如果没有给出方向,则通道是双向的。一个 通道可能仅限于发送或仅接收 转换或转让。
您可以通过转换或分配明确说明频道指示。例如,通过转换,
package main
import (
"fmt"
"time"
)
func Thread(r <-chan int) {
for {
num := <-r
fmt.Println("Thread : ", num)
time.Sleep(time.Second)
}
}
func main() {
c := make(chan int, 3)
s, r := (chan<- int)(c), (<-chan int)(c)
go Thread(r)
for i := 1; i <= 10; i++ {
s <- i
}
for len(c) > 0 {
time.Sleep(100)
}
}
输出:
Thread : 1 Thread : 2 Thread : 3 . . .
或者,等同地,通过作业,
package main
import (
"fmt"
"time"
)
func Thread(r <-chan int) {
for {
num := <-r
fmt.Println("Thread : ", num)
time.Sleep(time.Second)
}
}
func main() {
c := make(chan int, 3)
var s chan<- int = c
var r <-chan int = c
go Thread(r)
for i := 1; i <= 10; i++ {
s <- i
}
for len(c) > 0 {
time.Sleep(100)
}
}
答案 1 :(得分:1)
Go允许创建像c := make(<-chan int)
这样的发送或接收频道,但是,我还没有遇到过用例。 github中有一个讨论here。
关于代码中的错误;
func Thread(c chan<- int) {
for {
num := <-c
fmt.Println("Thread : ", num)
time.Sleep(time.Second)
}
}
只能将函数参数c
发送给。尝试从c接收将导致编译器错误,但行num := <-c
尝试接收。
最后,修正版;
package main
import (
"fmt"
"time"
)
func Thread(c <-chan int) {
for {
num := <-c
fmt.Println("Thread : ", num)
time.Sleep(time.Second)
}
}
func main() {
c := make(chan int, 3)
go Thread(c)
for i := 1; i <= 10; i++ {
c <- i
}
for len(c) > 0 {
time.Sleep(100)
}
}
答案 2 :(得分:0)
您的Thread
功能正在传递仅发送频道,而不是仅接收频道。但是,您不需要make()
它只接收,您可以将双向通道传递给goroutine作为仅接收。
package main
import (
"fmt"
"time"
)
func Thread(c <-chan int) {
for {
num := <-c
fmt.Println("Thread : ", num)
time.Sleep(time.Second)
}
}
func main() {
c := make(chan int, 3)
go Thread(c)
for i := 1; i <= 10; i++ {
c <- i
}
for len(c) > 0 {
time.Sleep(100)
}
}
您可以通过添加行
来验证这一点c <- 3
在Thread
函数中,抛出错误prog.go:11: invalid operation: c <- 3 (send to receive-only type <-chan int)