For loop 更新映射中的键,同时在该映射上迭代

For loop 更新映射中的键,同时在该映射上迭代,for-loop,go,For Loop,Go,我想使用URL参数将密钥从一个名称更新为另一个名称。我有代码,但输出不正确。见下文 这是地图 var data map[string][]string 函数im调用的PUT方法 r.HandleFunc("/updatekey/{key}/{newkey}", handleUpdateKey).Methods("PUT") handleUpdateKey函数,它被精确地解释了它在做什么 func handleUpdateKey(w http.ResponseWriter, r *http.R

我想使用URL参数将密钥从一个名称更新为另一个名称。我有代码,但输出不正确。见下文

这是地图

var data map[string][]string
函数im调用的PUT方法

r.HandleFunc("/updatekey/{key}/{newkey}", handleUpdateKey).Methods("PUT")
handleUpdateKey函数,它被精确地解释了它在做什么

func handleUpdateKey(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)

k := params["key"] //get url params
nk := params["newkey"]

s := make([]string, len(data[k])) //create slice of string to store map variables
for i := range data {             //range over the data map
    fmt.Fprintf(w, i)
    if k != i { //check if no keys exist with URL key param
        fmt.Fprintf(w, "That KEY doesn't exist in memory")
        break //kill the loop
    } else { //if there is a key the same as the key param
        for _, values := range data[i] { //loop over the slice of string (values in that KEY)
            s = append(s, values) //append all those items to the slice of string
        }

        delete(data, k) //delete the old key

        for _, svalues := range s { //loop over the slice of string we created earlier
            data[nk] = append(data[nk], svalues) //append the items within the slice of string, to the new key... replicating the old key, with a new key name
        }
    }
}
}
下面的代码应该将该键的所有值分配给一个字符串片段,稍后我们将对其进行迭代并添加到新键中。这是可行的,但是,输出如下,这显然是不正确的

KEY: catt: VALUE: 
KEY: catt: VALUE: 
KEY: catt: VALUE: zeus
KEY: catt: VALUE: xena
旧输出:

KEY: dog: VALUE: zeus
KEY: dog: VALUE: xena
更正新输出:

KEY: catt: VALUE: zeus
KEY: catt: VALUE: xena

在大多数语言中,更改您正在迭代的结构会导致奇怪的事情发生。特别是地图。你必须找到另一种方法

幸运的是,根本不需要迭代。您的循环只是一个大的if/else语句。如果密钥匹配,请执行某些操作。如果没有,那就做点别的。因为这是一个映射,所以不需要使用迭代搜索密钥,它可以直接查找。也不需要为了复制映射值而进行所有费劲的循环

if val, ok := data[k]; ok {
    // Copy the value
    data[nk] = val
    // Delete the old key
    delete(data, k)
} else {
    fmt.Fprintf(w, "The key %v doesn't exist", k)
}
最后,避免在函数中使用全局变量。如果函数可以更改全局变量,则很难理解它对程序的影响<代码>数据应传递到函数中以使其清晰

func handleUpdateKey(w http.ResponseWriter, r *http.Request, data map[string][]string)

在对贴图进行迭代时,不要对其进行变异。您可以更改值,但不应添加或删除任何项目。此外,如果您试图修改地图中的键,则应重新考虑您的设计。正如您从必须删除并重新添加项以更改键中看到的,映射键是不可变的。也许你只是想要一个项目的切片,其中每个项目都有键字段?你是说像一个结构?密钥和值存储在里面?是的,就像一个结构。非常感谢!感谢您的帮助:)我现在正试图删除一个值。。。如前所述,你永远不应该通过一个范围循环来改变地图,那么我该如何使用这个方法呢<代码>如果v,则ok:=数据[k];确定{data[k]=append(data[k][:i],data[k][i+1:]…)fmt.Fprintf(w,“键:%v:值:%v已成功删除”,k,v)@RossBown这只是你需要担心的关键点。你可以随意更改值。但是这里没有更多的迭代,所以你是安全的。现在还不清楚你想在那里做什么。问另一个问题。我只想从映射中的字符串片段中删除一个值……我是否循环遍历这些值并删除其中一个h与URL中的参数匹配……或者有更好的方法吗?从我在文档中看到的情况来看,没有一种方法可以通过值的名称循环并删除该值,但是您必须找到索引,然后将其删除。@RossBown从切片中删除值与更改其在映射中的键是一个单独的问题。问另一个问题。@罗斯伯恩湖