Golang学习日志 ━━ map等类型的指针分析

学习时遇到了map内含结构体,却不能使用map[string].int=1的方式进行直接修改,查了一下是因为golang出于安全原因,将map中的索引的值设定为不可寻址,即意味着无法直接修改该map索引下结构体内的字段。

解决方法也很简单,其中一种就是让map记住结构体的指针,而不是结构体本身。这样根据结构体指针就能找到该结构体及其字段了。

type archive struct {
	name string
	age  int
}
v1 := map[int64]*archive{
	10010: &archive{
		name: "xiaoli",
		age:  1,
	},
}
fmt.Println("v1[10010].age:", v1[10010].age) // v1[10010].age: 1

v1[10010].age = 2
fmt.Println("v1[10010].age:", v1[10010].age) // v1[10010].age: 2

fmt.Printf("v1:%v %T %p\n", v1, v1, v1)
// v1:map[10010:0xc000004660] map[int64]*pkg.archive 0xc00006eb70

写了如下的代码再看了一遍几种指针的情况,确实map与众不同。

//==============================测试普通
var m0 = int64(101)
fmt.Printf("m0:%v %T %p\n", m0, m0, m0) // m0:101 int64 %!p(int64=101)
fmt.Printf("&m0:%v %T %p\n", &m0, &m0, &m0) // &m0:0xc00000c318 *int64 0xc00000c318

//==============================测试map
var m1 = map[string]int{"a": 1, "b": 2}
fmt.Printf("m1:%v %T %p\n", m1, m1, m1) // m1:map[a:1 b:2] map[string]int 0xc00006ebd0
fmt.Printf("&m1:%v %T %p\n", &m1, &m1, &m1) // &m1:&map[a:1 b:2] *map[string]int 0xc000006030

// map类型不能获得索引地址,即不可取地址
// pkg\keng_ShowMapNoaddress.go:14:8: cannot take the address of m1["a"]
// m3 := &m1["a"]
// fmt.Printf("m3:%v %T\n", m3, m3)

//==============================测试切片
// 与map类型一样
var s1 = []string{"a", "b"}
fmt.Printf("s1:%v %T %p\n", s1, s1, s1) // s1:[a b] []string 0xc000004760
fmt.Printf("&s1:%v %T %p\n", &s1, &s1, &s1) // &s1:&[a b] *[]string 0xc000004740

// slice类型可以获得索引值得地址
fmt.Printf("&s1[0]:%v %T %p\n", &s1[0], &s1[0], &s1[0]) // &s1[0]:0xc000004760 *string 0xc000004760
fmt.Printf("&s1[1]:%v %T %p\n", &s1[1], &s1[1], &s1[1]) // &s1[1]:0xc000004770 *string 0xc000004770

//==============================测试结构体
type st struct {
	name string
	age  int
}
var st1 = st{
	name: "a",
	age:  1,
}
var st2 = st{
	name: "b",
	age:  2,
}
type stt struct {
	address string
	st
}
var stt1 = stt{
	address: "地址",
	st:      st2,
}

// 和普通一样,就是本例中的m0,%p不可,与map和slice不同
fmt.Printf(" st1:%v %T %p\n st2:%v %T %p\n stt1:%v %T %p\n", st1, st1, st1, st2, st2, st2, stt1, stt1, stt1)
// st1:{a 1} pkg.st %!p(pkg.st={a 1})
// st2:{b 2} pkg.st %!p(pkg.st={b 2})
// stt1:{地址 {b 2}} pkg.stt %!p(pkg.stt={地址 {b 2}})
 
fmt.Printf(" &st1:%v %T %p\n &st2:%v %T %p\n &stt1:%v %T %p\n", &st1, &st1, &st1, &st2, &st2, &st2, &stt1, &stt1, &stt1)
// &st1:&{a 1} *pkg.st 0xc000004800
// &st2:&{b 2} *pkg.st 0xc000004820
// &stt1:&{地址 {b 2}} *pkg.stt 0xc00006ed20
 
// 可以获得结构体内,包括嵌套结构体内的字段所在地址
fmt.Printf(" &st1.name:%v %T %p\n &st2.name:%v %T %p\n &stt1.address:%v %T %p\n &stt1.st.name:%v %T %p\n", &st1.name, &st1.name, &st1.name, &st2.name, &st2.name, &st2.name, &stt1.address, &stt1.address, &stt1.address, &stt1.st.name, &stt1.st.name, &stt1.st.name)
// &st1.name:0xc000004800 *string 0xc000004800
// &st2.name:0xc000004820 *string 0xc000004820
// &stt1.address:0xc00006ed20 *string 0xc00006ed20
// &stt1.st.name:0xc00006ed30 *string 0xc00006ed30

学习资料

GoLang基础数据类型—>字典(map)详解
Golang中哪些值是不可以寻址的
Golang map 的底层实现
Go语言map底层浅析

发布了44 篇原创文章 · 获赞 1 · 访问量 3595

猜你喜欢

转载自blog.csdn.net/snans/article/details/104110828
今日推荐