重命名地图中键的惯用方式,同时覆盖原始地图

I'm attempting to rename the keys of a map o using the keys and values of another map r.

This below attempt seems to fail for reasons I guess are related to the fact that I'm modifying the map while also ranging over it — I get an extra blank key.

I could simply copy the map over to a new destination map, however the map is part of a much more complex struct — so any attempts will require me to do some kind of recursive deep copy of that struct, which I would rather avoid.

o := make(map[string]string) // original map
r := make(map[string]string) // replacement map original -> destination keys

o["a"] = "x"
o["b"] = "y"

r["a"] = "1"
r["b"] = "2"

fmt.Println(o) // -> map[a:x b:y]

for k, v := range o {
    o[r[k]] = v
}

delete(o, "a")
delete(o, "b")

fmt.Println(o) // -> map[1:x 2:y :y]

I am expecting this to print map[1:x 2:y].

PEBKAC as always, this seems to solve it quite nicely by first checking if the replacement key is present in the replacement map and also deletes it in one fell swoop

for k, v := range o {
    if _, ok := r[k]; ok {
        o[r[k]] = v
        delete(o, k)
    }
}

If you range over and modify targeted map at same time, it gives an unexpected behavior which empty key with value. I have seen that before (it happens some time not always). I have not researched around it (may be fellow SO members can shed some light here).

If you do range over source map and update targeted map, you get a desired behavior.

for k, v := range r {
    o[v] = o[k]
    delete(o, k)
}

Output:

Modified map: map[1:x 2:y]

Play link: https://play.golang.org/p/heVbZFe0Nu

Simply iterate over the other map:

o := make(map[string]string) // original map
r := make(map[string]string) // replacement map original -> destination keys

o["a"] = "x"
o["b"] = "y"

r["a"] = "1"
r["b"] = "2"

fmt.Println(o) // -> map[a:x b:y]

for k, v := range r {
    o[v] = o[k]
    delete(o, k)
}
fmt.Println(o) // -> map[1:x 2:y]