Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dictionary 可以使用什么数据结构来支持外键约束_Dictionary_Go_Data Structures_Tree_Big O - Fatal编程技术网

Dictionary 可以使用什么数据结构来支持外键约束

Dictionary 可以使用什么数据结构来支持外键约束,dictionary,go,data-structures,tree,big-o,Dictionary,Go,Data Structures,Tree,Big O,给定一些上下文,我正在使用gRPC在服务器上实现扇出(流),每次客户端连接时,我都会将流保存到映射中,当客户端断开连接时,我只是将其从映射中删除,这样我就可以仅使用“活动”客户端/连接更新映射 因此,初始地图如下所示: key value client1 stream client2 stream client3 stream 此实现的问题是,如果客户端多次连接,则只有最后一个客户端(使用相同的密钥id)将接收“广播”消息,因为映射将用连接客户端的最新消息覆盖现

给定一些上下文,我正在使用gRPC在服务器上实现扇出(流),每次客户端连接时,我都会将流保存到映射中,当客户端断开连接时,我只是将其从映射中删除,这样我就可以仅使用“活动”客户端/连接更新映射

因此,初始地图如下所示:

key        value
client1    stream
client2    stream
client3    stream
此实现的问题是,如果客户端多次连接,则只有最后一个客户端(使用相同的
密钥id
)将接收“广播”消息,因为映射将用连接客户端的最新消息覆盖现有流,因此我需要使用唯一密钥或找到匹配的方法,联系客户和联系

我发现很容易切换地图,并将连接ID用作键,类似这样

conn_id   client_id
conn1     client1
conn2     client2 \
conn3     client2  > 3 connections for client ID 2
conn4     client2 /
这可以工作并有助于向所有连接的客户端发送消息,但如果我想向特定的客户端发送消息,则会使事情变得更复杂,因为我需要对整个映射进行范围/遍历,以便将值与所需的客户端相匹配

为了解决这个问题,我使用client_id切换回了映射,但是没有使用流作为值,而是使用了一个切片列表

key        value
client1   [stream, stream, stream]
client2   [stream]
client3   [stream, stream] 
问题仍然存在,因为为了向所有客户端发送消息,仍然需要遍历/范围完整映射,以获取每个客户端的流并向每个客户端发送消息

因此,在不使用数据库的情况下,我们可以按照与数据库相关的最佳实践使用什么样的数据结构

主要希望找到与数据库行为类似的东西,可能有两个映射,一个保持所有连接,另一个保持每个客户端的状态或连接数,例如:

key      value            client_id   # streams 
conn1    client1          client1     1   
conn2    client2          client2     3
conn3    client2
conn4    client2
但是,当
连接
映射中没有来自该客户机的更多连接时,如何“自动”从
客户机
映射中删除该客户机

这是一个尝试,但不知道是否可以改进:

主程序包
进口(
“fmt”
“同步”
)
func main(){
客户端:=&sync.Map{}
对于i:=0;i<100;i++{
clientID:=fmt.Sprintf(“客户端-%d”,i%5)
connID:=fmt.Sprintf(“conn-%d”,i)
client,ok:=clients.LoadOrStore(clientID,connID)
如果可以的话{
开关c:=客户端。(类型){
大小写字符串:
客户端=[]字符串{c,connID}
大小写[]字符串:
client=append(客户端([]字符串),connID)
}
clients.Store(clientID,client)
}
}
列表:=func(k,v接口{})bool{
fmt.Printf(“k:%+v:%v\n”,k,v)
返回真值
}
客户机范围(列表)
//获取所有连接
广播:=func(k,v接口{})bool{
fmt.Printf(“到来自%q\n”,k)的所有连接)
对于u,v:=范围v.([]字符串){
fmt.Printf(“连接消息=%s\n”,v)
}
返回真值
}
客户端。范围(广播)
}
在这里,我的仅尝试使用映射(易于处理删除)速度较慢,但分配的字节更少:

主程序包
进口(
“fmt”
“同步”
)
func main(){
客户端:=&sync.Map{}
对于i:=0;i<100;i++{
clientID:=fmt.Sprintf(“客户端-%d”,i%5)
connID:=fmt.Sprintf(“conn-%d”,i)
conns,ok:=clients.Load(clientID)
如果可以的话{
conns.(*sync.Map).Store(connID,i)
}否则{
连接:=&sync.Map{}
康奈德百货公司(康奈德,i)
客户商店(康涅狄格州客户ID)
}
}
列表:=func(k,v接口{})bool{
fmt.Printf(“k:%v\n”,k)
listValue:=func(j,l接口{})bool{
fmt.Printf(“j=%+v\n”,j)
返回真值
}
v、 (*sync.Map).范围(listValue)
返回真值
}
客户机范围(列表)
//获取所有连接
广播:=func(k,v接口{})bool{
fmt.Printf(“到来自%q\n”,k)的所有连接)
listValue:=func(j,l接口{})bool{
fmt.Printf(“连接的消息=%s--%v\n”,j,l)
返回真值
}
v、 (*sync.Map).范围(listValue)
返回真值
}
客户端。范围(广播)
}
package main

import (
    "fmt"
    "sync"
)

func main() {

    clients := &sync.Map{}
    for i := 0; i < 100; i++ {
        clientID := fmt.Sprintf("client-%d", i%5)
        connID := fmt.Sprintf("conn-%d", i)
        client, ok := clients.LoadOrStore(clientID, connID)
        if ok {
            switch c := client.(type) {
            case string:
                client = []string{c, connID}
            case []string:
                client = append(client.([]string), connID)
            }
            clients.Store(clientID, client)
        }
    }

    list := func(k, v interface{}) bool {
        fmt.Printf("k: %+v v: %v\n", k, v)
        return true
    }

    clients.Range(list)

    // Get all connections
    broadcast := func(k, v interface{}) bool {
        fmt.Printf("To all connections from= %q\n", k)
        for _, v := range v.([]string) {
            fmt.Printf("msg to conn = %s\n", v)
        }
        return true
    }
    clients.Range(broadcast)
}
package main

import (
    "fmt"
    "sync"
)

func main() {
    clients := &sync.Map{}
    for i := 0; i < 100; i++ {
        clientID := fmt.Sprintf("client-%d", i%5)
        connID := fmt.Sprintf("conn-%d", i)
        conns, ok := clients.Load(clientID)
        if ok {
            conns.(*sync.Map).Store(connID, i)
        } else {
            conns := &sync.Map{}
            conns.Store(connID, i)
            clients.Store(clientID, conns)
        }
    }

    list := func(k, v interface{}) bool {
        fmt.Printf("k: %v\n", k)
        listValue := func(j, l interface{}) bool {
            fmt.Printf("  j = %+v\n", j)
            return true
        }
        v.(*sync.Map).Range(listValue)
        return true
    }

    clients.Range(list)

    // Get all connections
    broadcast := func(k, v interface{}) bool {
        fmt.Printf("To all connections from= %q\n", k)
        listValue := func(j, l interface{}) bool {
            fmt.Printf("  msg to conn = %s -- %v\n", j, l)
            return true
        }
        v.(*sync.Map).Range(listValue)
        return true
    }
    clients.Range(broadcast)
}