golang创建多级字符串映射

I am very new to Go language. I am struggling with following usecase.

I want to store session id (string) and reqeust No (string) in a map for duplicate checking. When there is no entry in the map, it should create one, else it should return a flag saying the entry already exists.

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
}

The problem I am facing is that the value is over written every time the function is called. What am I doing wrong here?

It's often simpler to use a struct key instead of a multi-level map: https://play.golang.org/p/WFlGi1rrVOm

sess variable always equals session1, so you just override value for key session1. You have to have indistinguishable keys.

If you want just check duplicates, just to this:

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
}

You only have to create a value of the inner map (the session map) if a map for the given session ID does not yet exists (and not if the given request number is not in it), else you clear any previously stored request numbers from it.

Since you are using bool as the value type for the inner map (session map), you can exploit this to write simpler code (indexing a map with a key that is not in it will yield the zero value of the value type, which is false for the bool type, properly telling the key is not in it):

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

    if sessMap[Reqno] {
        return true
    }
    sessMap[Reqno] = true
    return false
}

Testing it:

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)
}

Output (try it on the Go Playground):

false map[session1:map[1:true]]
false map[session1:map[1:true 2:true]]
false map[session1:map[1:true 2:true 3:true]]
true map[session1:map[2:true 3:true 1:true]]
false map[session1:map[2:true 3:true 4:true 1:true]]
map[]

Note that bool –although may be small–does require memory. Since we can query if a key is in the map, we may opt to use a value type that requires no memory, such as an empty struct (struct{}). With that, it may look like this:

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
}

Testing and result is (almost) the same, try it on the Go Playground.

A word of warning: judging from the example, it looks you want to use this to track if a (web) request has been served previously, where usually multiple goroutines are involved. This solution is not safe for concurrent use.