golang создает многоуровневую строковую карту - PullRequest
0 голосов
/ 09 мая 2018

Я очень плохо знаком с языком го. Я борюсь со следующим вариантом использования.

Я хочу сохранить идентификатор сеанса (строка) и запрос Нет (строка) на карте для проверки дубликатов. Если на карте нет записи, она должна создать ее, иначе она должна вернуть флаг, говорящий о том, что запись уже существует.

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
}

Проблема, с которой я сталкиваюсь, заключается в том, что значение перезаписывается при каждом вызове функции. Что я тут не так делаю?

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

Вам нужно создать значение внутренней карты (карты сеанса) только в том случае, если карта для данного идентификатора сеанса еще не существует (и не , если данный номер запроса отсутствует в нем) иначе вы удалите с него все ранее сохраненные номера запросов.

Поскольку вы используете bool в качестве типа значения для внутренней карты (карты сеанса), вы можете использовать это для написания более простого кода (индексирование карты с ключом, которого в ней нет, даст нулевое значение тип значения (false для типа bool, правильно указывающий, что ключ не в нем):

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
}

Тестирование:

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

Вывод (попробуйте на 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[]

Обратите внимание, что 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
}

Тестирование и результат (почти) совпадают, попробуйте на Go Playground .

Слово предупреждения: судя по примеру, похоже, что вы хотите использовать это, чтобы отследить, был ли (веб) запрос был обслужен ранее, где обычно задействовано несколько goroutines. Это решение небезопасно для одновременного использования .

0 голосов
/ 10 мая 2018

Часто проще использовать структурный ключ вместо многоуровневой карты: https://play.golang.org/p/WFlGi1rrVOm

0 голосов
/ 09 мая 2018

переменная 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...