正常demo1
type student struct {
Name string
Age int
}
func main() {
m := make(map[string]student)
stus := []student{
{Name: "zhou", Age: 24},
{Name: "li", Age: 23},
{Name: "wang", Age: 22},
}
for _, stu := range stus {
m[stu.Name] = stu
}
for k,v:=range m{
fmt.Println(k,"=>",v)
}
}
输出
zhou => {zhou 24}
li => {li 23}
wang => {wang 22}
得到m后,如果对stus
进行值修改,比如
stus[0].Age = 1000
//再次输出
for k,v:=range m{
fmt.Println(k,"=>",v)
}
得到结果为,
zhou => {zhou 24}
li => {li 23}
wang => {wang 22}
zhou => {zhou 24}
li => {li 23}
wang => {wang 22}
证明以上为值传递写法,修改源stus,并不影响m
滥用指针 demo2?
type student struct {
Name string
Age int
}
func main() {
m := make(map[string]*student) //注意区别,这是指针类型,必须要指针赋值操作
stus := []student{
{Name: "zhou", Age: 24},
{Name: "li", Age: 23},
{Name: "wang", Age: 22},
}
for _, stu := range stus {
m[stu.Name] = &stu //如果不加“&”会报错
}
for k,v:=range m{
fmt.Println(k,"=>",*v) //需要打印出值
}
}
输出
zhou => {wang 22}
li => {wang 22}
wang => {wang 22}
很明显,传递的是一个变量stu
的指针,而不是值;因为这个变量的值始终在变,但变量的指针不变;导致打印出的是变化的最终值。
接下来正确方法,
for _, stu := range stus {
m[stu.Name] = &stu
}
=>
for k, stu := range stus {
m[stu.Name] = &stus[k]
}
这样,把stus
值得每个元素的指针传递给了m种的值(指针),这样就输出的就是对了,
zhou => {zhou 24}
li => {li 23}
wang => {wang 22}
得到了m后,如果再对stus
得值进行修改,比如
stus[0].Age = 1000
最终得到结果,也跟着变化
li => {li 23}
wang => {wang 22}
zhou => {zhou 1000}
证明以上分析正确性。
总结
- 对比以上两种方式,第一种要安全一些,第二种性能好一些;但提倡第一种写法;能不显式定义指针就不要定义。