在不同的go例程中读取/写入记录集-使用哪种数据结构

问题描述 投票:1回答:2

我有一个使用2个go例程的聊天应用程序。我想在一个线程中向/从列表中删除记录,或者从另一个线程中读取相同的列表。

由于我在Go语言中还很陌生,所以我对应该使用哪种数据结构感到有些困惑。我想到了切片,但不确定是否以正确的方式使用它]

func listener(addr *net.UDPAddr, clients *[] *net.UDPAddr, messages chan clientMessage) {

    for {
            *clients=append(*clients,otherAddr)     
    }
}

func sender(messages chan clientMessage,clients *[] *net.UDPAddr) {

  for {
    message :=<- messages
    for _,client := range *clients {
            fmt.Printf("Message %s sent to %s\n", message.message, client.String())

    }
  }
}


func main() {   
    var clients [] *net.UDPAddr
    go listener(s,&clients,messageCh)
    go sender(messageCh,&clients) 
}
go data-structures slice
2个回答
1
投票

对于该场景,切片看起来不错,但是需要mutex来防止并发读取和写入切片。

让切片和互斥锁捆绑在一个结构中,并为两个操作添加方法:添加和枚举。

type clients struct {
    mu     sync.Mutex
    values []*net.UDPAddr
}

// add adds a new client
func (c *clients) add(value *net.UDPAddr) {
    c.mu.Lock()
    c.values = append(c.values, value)
    c.mu.Unlock()
}

// do calls fn for each client
func (c *clients) do(fn func(*net.UDPAddr) error) error {
    c.mu.Lock()
    defer c.mu.Unlock()
    for _, value := range c.values {
        if err := fn(value); err != nil {
            return err
        }
    }
    return nil
}

像这样使用它:

func listener(addr *net.UDPAddr, clients *clients, messages chan clientMessage) {
    for {
        clients.add(otherAddr)
    }
}

func sender(messages chan clientMessage, clients *clients) {

    for {
        message := <-messages
        clients.do(func(client *net.UDPAddr) error {
            fmt.Printf("Message %s sent to %s\n", message.message, client.String())
            return nil
        })
    }
}

func main() {
    var clients clients
    go listener(s, &clients, messageCh)
    go sender(messageCh, &clients)
}

0
投票

由于侦听器只需要写,发送者只需要读-这是使用通道进行通信的一个很好的例子。流程如下所示:

  1. 侦听器会将新客户端发布到频道。
  2. 发件人将收到新的客户端,并将更新其本地切片客户。

这样会更清洁,更安全-因为侦听器将无法“意外”读取并且发送者将无法“意外”写入。侦听器也可以关闭频道,以向发送方指示已完成。

© www.soinside.com 2019 - 2024. All rights reserved.