Dictionary golang创建多级字符串映射

Dictionary golang创建多级字符串映射,dictionary,go,Dictionary,Go,我是一个非常新的语言。我正在努力解决以下用例 我想将会话id(字符串)和请求编号(字符串)存储在映射中以进行重复检查。当地图中没有条目时,它应该创建一个条目,否则它应该返回一个标志,表明该条目已经存在 package main import "fmt" func main() { mySessionData := make(map[string]map[string]bool) var ret bool ret = chkDuplicate(mySessionDat

我是一个非常新的语言。我正在努力解决以下用例

我想将会话id(字符串)和请求编号(字符串)存储在映射中以进行重复检查。当地图中没有条目时,它应该创建一个条目,否则它应该返回一个标志,表明该条目已经存在

package main

import "fmt"

func main() {
    mySessionData := make(map[string]map[string]bool)

    var ret bool
    ret = chkDuplicate(mySessionData, "session1", "1")
    fmt.Println(mySessionData)
    ret = chkDuplicate(mySessionData, "session1", "2")
    fmt.Println(mySessionData)
    ret = chkDuplicate(mySessionData, "session1", "3")
    fmt.Println(mySessionData)
    ret = chkDuplicate(mySessionData, "session1", "2")
    fmt.Println(mySessionData)
    ret = chkDuplicate(mySessionData, "session1", "4")
    fmt.Println(mySessionData)
    fmt.Println(ret)

    delete(mySessionData, "session1")
    fmt.Println(mySessionData)

}

func chkDuplicate(m map[string]map[string]bool, sess string, Reqno string) bool {
    var found bool
    val, found := m[sess][Reqno]
    if !found {
        fmt.Println(val)
        valu := make(map[string]bool)
        valu[Reqno] = true
        m[sess] = valu
        return !found

    }
    return !found
}
我面临的问题是,每次调用函数时,值都被过度写入。
我做错了什么?

sess变量始终等于session1,所以您只需重写键session1的值。你必须有难以辨别的钥匙

如果要检查重复项,请执行以下操作:

package main 

import "fmt"

func main() {
    mySessionData := make(map[string]bool)

    chkDuplicate(mySessionData, "session1", "1")
    chkDuplicate(mySessionData, "session1", "1")
    chkDuplicate(mySessionData, "session2", "1")
    fmt.Println(mySessionData) # two keys printed
}

func chkDuplicate(m map[string]bool, sess string, Reqno string) bool {
    key := fmt.Sprintf("%s-%s", sess, Reqno)
    _, found := m[key]
    if !found {
       m[key] = true    
    }
   return !found
}

sess变量始终等于session1,所以您只需覆盖键session1的值。你必须有难以辨别的钥匙

如果要检查重复项,请执行以下操作:

package main 

import "fmt"

func main() {
    mySessionData := make(map[string]bool)

    chkDuplicate(mySessionData, "session1", "1")
    chkDuplicate(mySessionData, "session1", "1")
    chkDuplicate(mySessionData, "session2", "1")
    fmt.Println(mySessionData) # two keys printed
}

func chkDuplicate(m map[string]bool, sess string, Reqno string) bool {
    key := fmt.Sprintf("%s-%s", sess, Reqno)
    _, found := m[key]
    if !found {
       m[key] = true    
    }
   return !found
}

如果给定会话ID的映射尚不存在(如果给定请求号不在其中,则不存在),则只需创建内部映射(会话映射)的值,否则从中清除以前存储的任何请求号

由于您使用
bool
作为内部映射(会话映射)的值类型,因此可以利用此功能编写更简单的代码(使用不在映射中的键对映射进行索引将生成值类型的零值,对于
bool
类型,此值为
false
,正确地告知键不在映射中):

测试它:

func main() {
    mySessionData := make(map[string]map[string]bool)

    for _, reqNo := range []string{"1", "2", "3", "2", "4"} {
        ret := chkDuplicate(mySessionData, "session1", reqNo)
        fmt.Println(ret, mySessionData)
    }

    delete(mySessionData, "session1")
    fmt.Println(mySessionData)
}
输出(在上尝试):

请注意,
bool
——虽然可能很小,但确实需要内存。因为我们可以查询键是否在映射中,所以我们可以选择使用不需要内存的值类型,例如空结构(
struct{}
)。因此,它可能看起来像这样:

func chkDuplicate(m map[string]map[string]struct{}, sess string, Reqno string) bool {
    sessMap := m[sess]
    if sessMap == nil {
        m[sess] = map[string]struct{}{Reqno: struct{}{}}
        return false
    }

    if _, ok := sessMap[Reqno]; ok {
        return true
    }
    sessMap[Reqno] = struct{}{}
    return false
}
测试和结果(几乎)是一样的,请在桌面上试用


警告一句:从这个例子来看,您似乎希望使用它来跟踪以前是否提供过(web)请求,其中通常涉及多个goroutine。此解决方案对于并发使用不安全

如果给定会话ID的映射尚不存在(并且如果给定的请求号不在其中,则不存在),则只需创建内部映射(会话映射)的值,否则从中清除以前存储的任何请求号

由于您使用
bool
作为内部映射(会话映射)的值类型,因此可以利用此功能编写更简单的代码(使用不在映射中的键对映射进行索引将生成值类型的零值,对于
bool
类型,此值为
false
,正确地告知键不在映射中):

测试它:

func main() {
    mySessionData := make(map[string]map[string]bool)

    for _, reqNo := range []string{"1", "2", "3", "2", "4"} {
        ret := chkDuplicate(mySessionData, "session1", reqNo)
        fmt.Println(ret, mySessionData)
    }

    delete(mySessionData, "session1")
    fmt.Println(mySessionData)
}
输出(在上尝试):

请注意,
bool
——虽然可能很小,但确实需要内存。因为我们可以查询键是否在映射中,所以我们可以选择使用不需要内存的值类型,例如空结构(
struct{}
)。因此,它可能看起来像这样:

func chkDuplicate(m map[string]map[string]struct{}, sess string, Reqno string) bool {
    sessMap := m[sess]
    if sessMap == nil {
        m[sess] = map[string]struct{}{Reqno: struct{}{}}
        return false
    }

    if _, ok := sessMap[Reqno]; ok {
        return true
    }
    sessMap[Reqno] = struct{}{}
    return false
}
测试和结果(几乎)是一样的,请在桌面上试用


警告一句:从这个例子来看,您似乎希望使用它来跟踪以前是否提供过(web)请求,其中通常涉及多个goroutine。此解决方案对于并发使用不安全

使用结构键而不是多级映射通常更简单:

使用结构键而不是多级映射通常更简单:

每次发现为false时,您都要创建一个新映射,不要这样做,检查m[sess]是否为nil,然后才创建它,如果不是nil,只需将m[sess][Reqno]设置为true即可。您没有在任何地方使用
val
变量,因为每次检查重复项时,您都会为
req
创建一个新映射。每次发现错误时,您都会创建一个新映射,不要这样做,请检查m[sess]是否为nil,然后才创建它,如果不是nil,请将m[sess][Reqno]设置为true。您没有在任何地方使用
val
变量,因为每次检查重复项时,您都要为
req
创建一个新映射。我正在寻找类似于Perl散列的东西。因此,当我访问mySessionData[“session1”][“2”]时,变量mySessionData应该能够返回值true,但当我说mySessionData[“session1”][“6”]时,则返回nil。我正在寻找类似于散列的Perl散列的东西。因此,当我访问mySessionData[“session1”][“2”]时,变量mySessionData应该能够返回值true,但当说mySessionData[“session1”][“6”]时,应该返回值nil