登录
首页 >  Golang >  Go问答

在 Go 中迭代无缓冲通道和处理超时

来源:stackoverflow

时间:2024-02-12 12:54:24 439浏览 收藏

学习知识要善于思考,思考,再思考!今天golang学习网小编就给大家带来《在 Go 中迭代无缓冲通道和处理超时》,以下内容主要包含等知识点,如果你正在学习或准备学习Golang,就都不要错过本文啦~让我们一起来看看吧,能帮助到你就更好了!

问题内容

在我的代码中,我有一个节点的连接图(所有节点都直接或间接地相互连接)。初始化时,每个节点都有一个 value,它是一个随机的 64 位整数。

type node struct {
    id *uuid.uuid

    value int64

    listenchannel chan message

    connections map[uuid.uuid]*node
}


type message struct {
    value int64
}

这个想法是,他们将相互沟通并就最大的 value 达成共识。 (通信通过每个节点具有的 listenchannel 进行,节点也被建模为 goroutine)

func (node *Node) FormConsensus(wg *sync.WaitGroup, retChannel chan int64) {
    defer wg.Done()
    defer func() {
        // this will be a non-blocking operation since the channel is buffered
        retChannel <- node.Value
    }()

    listenWg := sync.WaitGroup{}

    listenWg.Add(1)
    // Add logic to pass messages to and fro and find the maximum value from the network
    go func() {
        for timedOut := false; !timedOut; {
            select {
            case receivedMessage := <-node.ListenChannel:
                if receivedMessage.Value > node.Value {
                    fmt.Println("Received value")
                    node.Value = receivedMessage.Value
                    fmt.Println("Received large value")
                    node.BroadcastValue()
                }
            case <-time.After(5 * time.Second):
                fmt.Println("Timeout")
                listenWg.Done()
                close(node.ListenChannel)
                timedOut = true
            }
        }
    }()

    node.BroadcastValue()
    listenWg.Wait()
}

func (node *Node) BroadcastValue() {
    fmt.Println("broadcasting", node.Value)
    for _, connection := range node.Connections {
        connection.ListenChannel <- Message{node.Value}
    }
}

为了实现这一点,每个节点首先将其值广播到其连接,并且还有一个 goroutine 持续在自己的 listenchannel 上侦听其他节点正在发送的值。如果接收到的值大于自己的值,则更新自己的值,并广播更新后的值。

通过 switch case 内部的超时逻辑,我尝试设置 5 秒的超时,即,如果 5 秒内通道上没有收到消息,则假设已达到共识并退出。

但是在执行 formconsensus 函数时,它永远不会退出。我不确定我哪里出错了,而且由于我对 go 很陌生,我可能会做一些完全不惯用的事情。除了了解出了什么问题之外,了解是否有更好的方法来实现我在 go 中尝试的目标也非常有帮助。


正确答案


我很确定错误就在这里。

func (node *Node) BroadcastValue() {
fmt.Println("broadcasting", node.Value)
for _, connection := range node.Connections {
    select {
    case connection.ListenChannel <- Message{node.Value}:
        fmt.Println("--test message written")
    default:
        fmt.Println("--test message dropped")
    }
}

}

看起来通道写入操作正在阻塞,因为缓冲区已满。您必须调查为什么它发送的消息比您预期的多。

到这里,我们也就讲完了《在 Go 中迭代无缓冲通道和处理超时》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>