m := make(map[string][]string)
m["like"] = []string{"a", "b"}
v := m["like"]
fmt.Println(m["like"])
v = append(v, "c")
fmt.Println(v)
fmt.Println(m["like"])
上述代码输出
[a b]
[a b c]
[a b]
我理解不了为什么没有修改键的值
append 会生成一个新的切片值,所以 v是重新指向了这个新的切片值,它原来指向的 m["like"] 还是原来的值
答案:
当键的值为切片时,修改其中一个切片会影响到同一个键对应的其他切片。这是因为在Go中,切片是引用类型,赋值操作时会将切片指向同一个底层数组,因此对其中一个切片的修改会反映到其他指向该数组的切片上。
以下是一个简单的示例代码,用来说明这个问题:
package main
import "fmt"
func main() {
m := make(map[int][]int)
// 初始化两个切片
m[1] = []int{1, 2, 3}
m[2] = []int{4, 5, 6}
// 修改其中一个切片
m[1][2] = 99
// 输出两个切片
fmt.Println(m[1]) // [1 2 99]
fmt.Println(m[2]) // [4 5 6]
}
可以看到,修改m[1]的值后,m[2]并没有受到影响,并依然保持原值。因此,要避免出现这种意外的修改,应该在对切片进行赋值或修改前,先使用copy()
函数将所赋的值或修改的值拷贝一份。这样,就可以避免因为共享同一个底层数组而发生的影响了。
以下是一个使用copy()
函数解决该问题的示例代码:
package main
import "fmt"
func main() {
m := make(map[int][]int)
// 初始化两个切片
m[1] = []int{1, 2, 3}
m[2] = []int{4, 5, 6}
// 拷贝一个一模一样的切片
v := make([]int, len(m[1]))
copy(v, m[1])
// 修改拷贝出来的切片
v[2] = 99
// 用拷贝出来的切片替换原来的切片
m[1] = v
// 输出两个切片
fmt.Println(m[1]) // [1 2 99]
fmt.Println(m[2]) // [4 5 6]
}
以上代码中,我们首先使用copy()
函数将m[1]的值拷贝一份,并将其修改为v[2]=99。然后,我们用修改后的v数组,替换掉原来的m[1]切片。这样,就避免了共享底层数组造成的意外修改了。