去阻止我的goroutine?

去阻止我的goroutine?,go,garbage-collection,Go,Garbage Collection,我一直在尝试从更传统的语言(如Java和C)进入Go,到目前为止,我一直很享受Go提供的经过深思熟虑的设计选择。当我开始我的第一个“真正的”项目时,我遇到了一个几乎没有人会遇到的问题 我的项目是一个发送和接收数据包的简单网络实现。一般结构如下(当然简化): 客户端通过服务器管理net.Conn。这个客户端创建了一个PacketReader和一个PacketWriter。它们都在不同的goroutine中运行无限循环。PacketReader采用一个接口,该接口具有一个由客户端实现的OnPacke

我一直在尝试从更传统的语言(如Java和C)进入Go,到目前为止,我一直很享受Go提供的经过深思熟虑的设计选择。当我开始我的第一个“真正的”项目时,我遇到了一个几乎没有人会遇到的问题

我的项目是一个发送和接收数据包的简单网络实现。一般结构如下(当然简化):

客户端通过服务器管理
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()