一个错误的使用Map示例(非常坑)

程序员成长之旅 · 程序员成长之旅/Go语言学习/笔记 · 984 字

先看代码 package main import "fmt" type student struct { Name string Age int } func pase_student() { m := make(map[string]*student) stus := []student{ {Name: "zhou", Age: 24}, {Name: "wrh", Age: 22}, {Name: "qiang", Age: 21}, } for _, stu := range stus { m[stu.Name] = &stu } for _,va:= range m{ fmt.Println(va.Name,":",va) } } func main() { pase_student() }

x

1 package

main 2 3 import

"fmt" 4 5 type

student

struct { 6

Name

string 7

Age

int 8 } 9 10 func

pase_student () { 11

m :

make ( map [ string ] * student ) 12

stus :

[] student { 13

{ Name : "zhou" , Age : 24 }, 14

{ Name : "wrh" , Age : 22 }, 15

{ Name : "qiang" , Age : 21 }, 16

} 17

for

_ , stu :

range

stus { 18

m [ stu . Name ]

& stu 19

} 20 21

for

_ , va :

range

m { 22

fmt . Println ( va . Name , ":" , va ) 23

} 24 } 25 26 func

main () { 27

pase_student () 28 } 猜一下结果? //结果 qiang : &{qiang 21} qiang : &{qiang 21} qiang : &{qiang 21}

1 //结果 2 qiang : & { qiang

21 } 3 qiang : & { qiang

21 } 4 qiang : & { qiang

21 } ???????? 看看问题在哪里 ↓ ↓ ↓ ↓ ↓ for _, stu := range stus {//每次循环并不会为stu新开一块内存,而是修改stu指向的值!!! m[stu.Name] = &stu//这里的"stu"其实是值类型的,但是每次遍历都是存储 "stu" 的指针,虽然每次range操作是修改了stu对应的值,但是stu的指针地址是从来都没有变,所以这里不能绝对这么使用!!!!! }

1

for

_ , stu :

range

stus { //每次循环并不会为stu新开一块内存,而是修改stu指向的值!!! 2

m [ stu . Name ]

& stu //这里的"stu"其实是值类型的,但是每次遍历都是存储 "stu" 的指针,虽然每次range操作是修改了stu对应的值,但是stu的指针地址是从来都没有变,所以这里不能绝对这么使用!!!!! 3

} //正确的思路(1) *推荐 : 既然用了指针就要用到底 package main import "fmt" type student struct { Name string Age int } func pase_student() { m := make(map[string]*student) stus := []*student{//这里的student使用了指针,毕竟用指针就要用到底嘛 {Name: "zhou", Age: 24}, {Name: "wrh", Age: 22}, {Name: "qiang", Age: 21}, } for _, stu := range stus { m[stu.Name] = stu } for _,va:= range m{ fmt.Println(va.Name,":",*va)//输出的时候使用了指针 } } func main() { pase_student() } //结果 zhou : {zhou 24} wrh : {wrh 22} qiang : {qiang 21} //正确的思路(2) : 既然不用指针,就都不要用指针,全部传数值! package main import "fmt" type student struct { Name string Age int } func pase_student() { m := make(map[string]student) stus := []student{ {Name: "zhou", Age: 24}, {Name: "wrh", Age: 22}, {Name: "qiang", Age: 21}, } for _, stu := range stus { m[stu.Name] = stu//这里的"stu"其实是值,但是每次遍历都是存储 "stu" 的指针,虽然每次range操作是修改了stu对应的值,但是stu的指针地址是从来都没有变,所以这里不能这么使用!!!!! } for _,va:= range m{ fmt.Println(va.Name,":",va) } } func main() { pase_student() } //结果 zhou : {zhou 24} wrh : {wrh 22} qiang : {qiang 21}

x

1 //正确的思路(1) *推荐 : 既然用了指针就要用到底 2 package

main 3 4 import

"fmt" 5 6 type

student

struct { 7

Name

string 8

Age

int 9 } 10 11 func

pase_student () { 12

m :

make ( map [ string ] * student ) 13

stus :

[] * student { //这里的student使用了指针,毕竟用指针就要用到底嘛 14

{ Name : "zhou" , Age : 24 }, 15

{ Name : "wrh" , Age : 22 }, 16

{ Name : "qiang" , Age : 21 }, 17

} 18

for

_ , stu :

range

stus { 19

m [ stu . Name ]

stu 20

} 21 22

for

_ , va :

range

m { 23

fmt . Println ( va . Name , ":" , * va ) //输出的时候使用了指针 24

} 25 } 26 27 func

main () { 28

pase_student () 29 } 30 //结果 31 zhou : { zhou

24 } 32 wrh : { wrh

22 } 33 qiang : { qiang

21 } 34 35 //正确的思路(2) : 既然不用指针,就都不要用指针,全部传数值! 36 package

main 37 38 import

"fmt" 39 40 type

student

struct { 41

Name

string 42

Age

int 43 } 44 45 func

pase_student () { 46

m :

make ( map [ string ] student ) 47

stus :

[] student { 48

{ Name : "zhou" , Age : 24 }, 49

{ Name : "wrh" , Age : 22 }, 50

{ Name : "qiang" , Age : 21 }, 51

} 52

for

_ , stu :

range

stus { 53

m [ stu . Name ]

stu //这里的"stu"其实是值,但是每次遍历都是存储 "stu" 的指针,虽然每次range操作是修改了stu对应的值,但是stu的指针地址是从来都没有变,所以这里不能这么使用!!!!! 54

} 55 56

for

_ , va :

range

m { 57

fmt . Println ( va . Name , ":" , va ) 58

} 59 } 60 61 func

main () { 62

pase_student () 63 } 64 //结果 65 zhou : { zhou

24 } 66 wrh : { wrh

22 } 67 qiang : { qiang

21 }