去阻止我的goroutine?
我一直在尝试从更传统的语言(如Java和C)进入Go,到目前为止,我一直很享受Go提供的经过深思熟虑的设计选择。当我开始我的第一个“真正的”项目时,我遇到了一个几乎没有人会遇到的问题 我的项目是一个发送和接收数据包的简单网络实现。一般结构如下(当然简化): 客户端通过服务器管理去阻止我的goroutine?,go,garbage-collection,Go,Garbage Collection,我一直在尝试从更传统的语言(如Java和C)进入Go,到目前为止,我一直很享受Go提供的经过深思熟虑的设计选择。当我开始我的第一个“真正的”项目时,我遇到了一个几乎没有人会遇到的问题 我的项目是一个发送和接收数据包的简单网络实现。一般结构如下(当然简化): 客户端通过服务器管理net.Conn。这个客户端创建了一个PacketReader和一个PacketWriter。它们都在不同的goroutine中运行无限循环。PacketReader采用一个接口,该接口具有一个由客户端实现的OnPacke
net.Conn
。这个客户端
创建了一个PacketReader
和一个PacketWriter
。它们都在不同的goroutine中运行无限循环。PacketReader
采用一个接口,该接口具有一个由客户端实现的OnPacketReceived
函数
PacketReader
代码如下所示:
go func() {
for {
bytes, err := reader.ReadBytes(10) // Blocks the current routine until bytes are available.
if err != nil {
panic(err) // Handle error
}
reader.handler.OnPacketReceived(reader.parseBytes(bytes))
}
}()
go func() {
for {
if len(reader.packetQueue) > 0 {
// Write packet
}
}
}()
type Client struct {
callbacks map[int]chan interface{}
// More fields
}
func (c *Client) OnPacketReceived(packet *Packet) {
c.callbacks[packet.Id] <- packet.Data
}
func (c *Client) SendDataBlocking(id int, data interface{}) interface{} {
c.PacketWriter.QueuePacket(data)
return <-c.callbacks[id]
}
PacketWriter
代码如下所示:
go func() {
for {
bytes, err := reader.ReadBytes(10) // Blocks the current routine until bytes are available.
if err != nil {
panic(err) // Handle error
}
reader.handler.OnPacketReceived(reader.parseBytes(bytes))
}
}()
go func() {
for {
if len(reader.packetQueue) > 0 {
// Write packet
}
}
}()
type Client struct {
callbacks map[int]chan interface{}
// More fields
}
func (c *Client) OnPacketReceived(packet *Packet) {
c.callbacks[packet.Id] <- packet.Data
}
func (c *Client) SendDataBlocking(id int, data interface{}) interface{} {
c.PacketWriter.QueuePacket(data)
return <-c.callbacks[id]
}
为了使客户端
阻塞,客户端创建一个通道,由OnPacketReceived
填充,如下所示:
go func() {
for {
bytes, err := reader.ReadBytes(10) // Blocks the current routine until bytes are available.
if err != nil {
panic(err) // Handle error
}
reader.handler.OnPacketReceived(reader.parseBytes(bytes))
}
}()
go func() {
for {
if len(reader.packetQueue) > 0 {
// Write packet
}
}
}()
type Client struct {
callbacks map[int]chan interface{}
// More fields
}
func (c *Client) OnPacketReceived(packet *Packet) {
c.callbacks[packet.Id] <- packet.Data
}
func (c *Client) SendDataBlocking(id int, data interface{}) interface{} {
c.PacketWriter.QueuePacket(data)
return <-c.callbacks[id]
}
类型客户端结构{
回调映射[int]chan接口{}
//更多领域
}
func(c*客户端)OnPacketReceived(packet*packet){
c、 根据s的评论,回调[packet.Id]将编写器更改为使用通道而不是切片(我甚至不知道为什么我首先这么做)。这似乎给了GC足够的“移动性”来允许线程停止。添加运行时.Gosched()
并仍然使用切片也起作用,但通道似乎更有效“go-esque”。我建议在你的问题中添加你的go版本和an,这样更多的人可以尝试重现并告诉你问题所在。不相关的旁注:在你的PacketWriter
中,你应该使用一个频道(和range
)与繁忙的for
循环相比,我的旁注可能没那么无关:尝试在writer中的for
循环中添加runtime.Gosched()