【发布时间】:2015-07-09 00:29:03
【问题描述】:
查看net.TCPListener。考虑到 Go 并发范式,人们会期望将此系统功能实现为通道,以便您从 Listen() 函数中获得 chan *net.Conn,或类似的东西。
但似乎 Accept() 是一种方式,它只是阻塞,就像系统接受一样。除了它是残废的,因为:
- 没有合适的 select() 可以用于它,因为 go 更喜欢频道
- 无法为服务器套接字设置阻塞选项。
所以我正在做类似的事情:
acceptChannel = make(chan *Connection)
go func() {
for {
rw, err := listener.Accept()
if err != nil { ... handle error ... close(acceptChannel) ... return }
s.acceptChannel <-&Connection{tcpConn: rw, .... }
}
}()
这样我就可以在一个选择中使用多个服务器套接字,或者将 Accept() 上的等待与其他通道多路复用。我错过了什么吗?我是 Go 新手,所以我可能会忽略一些事情——但 Go 真的没有用自己的并发范式实现自己的阻塞系统功能吗?我真的需要为每个我想听的套接字(可能数百或数千个)单独的 goroutine 吗?这是要使用的正确成语,还是有更好的方法?
【问题讨论】:
-
goroutines 不是线程。然而,它们是处理语言中并发操作的正确方法,例如等待来自多个套接字的接受。
-
您或许应该观看此视频youtube.com/watch?v=cN_DpYBzKso,并且通常尝试重新考虑频道,因为您不了解频道的目的或如何使用它们来控制节目的流程......频道可以作为一种阻塞机制,除了它们的主要用途是将数据传入和传出 goroutines 之外。将连接传递到通道是没有意义的。更明智的应用是将通道传递给您在 goroutine 中调用的方法,在那里打开连接并将数据发送回通道上的调用者。也许你在那里有一个阻塞选择......
-
@evanmcdonnal - 你能给我看一个你建议的方法的例子吗?我不明白你在说什么。我正在尝试将来自多个套接字的accept() 与其他通道recvs 复用。
-
Go 不是 Node.js。您可以很好地生成 50k goroutines,并且阻塞 I/O 是根据异步 I/O 实现的。
-
供将来参考,而不是对语言 X 无法按照您认为的方式工作表示怀疑;只需用 X 语言解释 what 您想做什么,并询问 如何,您就会得到更好的回应。
标签: tcp concurrency go