golang 之 Map 思考

小朋友.jpeg

1. 写在最前面

最近 review 代码的时候,遇到了很多 map[string]pointer 的写法,之前这种写法的时候,笔者总是以 C/C++ 的角度思考,这样写其实是为了节省内存,但其实不然,除了节省内存,还有其他的意义。

2. 值 vs 指针修改生效问题

先看一个例子,定义一个结构体,其存在两种方法:

  • 值类的方法
  • 指针类的方法
package main
​
import "fmt"
​
type Person struct {
  name string
  age  int
}
​
// 指针类的方法
func (p *Person) updateName(n string) {
  p.name = n
}
​
// 值类的方法
func (p Person) updateAge(a int) {
  p.age = a
}
​
func updateByValue() {
  p := Person{
    name: "xiyan",
    age:  28,
  }
  fmt.Printf("updateByValue before %v\n", p)
  p.updateAge(29)
  p.updateName("new-xiyan")
  fmt.Printf("updateByValue after %v\n", p)
}
​
func updateByPointer() {
  p := &Person{
    name: "xiyan",
    age:  28,
  }
  fmt.Printf("updateByPointer before %v\n", p)
  p.updateAge(29)
  p.updateName("new-xiyan")
  fmt.Printf("updateByPointer after %v\n", p)
}
​
func main() {
  updateByValue() // 值的修改方法不生效
  fmt.Println("=================================")
  updateByPointer() // 指针的修改方法生效
}
​
复制代码

结论:只有定义为指针的方法的修改才能生效。

值和指针.png

3. 值 vs 指针修改寻址问题

还是上述的例子,直接寻址 map 中定义的值和指针类型的结构体:

package main
​
type Person struct {
  name string
  age  int
}
​
func (p *Person) updateName(n string) {
  p.name = n
}
​
func (p Person) updateAge(a int) {
  p.age = a
}
​
func main() {
  m1 := map[string]*Person{
    "xiyan": {
      name: "xiyan",
      age:  28,
    },
  }
  // 指针类型的结构体能够直接寻址
  (m1["xiyan"]).name = "hehe"
​
  m2 := map[string]Person{
    "xiyan": {
      name: "xiyan",
      age:  28,
    },
  }
  // 值类型的结构体不能够直接寻址
  (m2["xiyan"]).name = "hehe"
  (m2["xiyan"]).age = 29
​
}
复制代码

结论:值类型结构体上的寻址会报错。cannot assign to struct field xxx in map

寻址.png

4. Why 什么值类型无法寻址

m2 的 value 存储的是 Person 结构体的值,所有m2["xiyan"] 不是一个常规的可寻址值:hashmaps 可以在运行时增长,然后它们的值在内存中移动,旧位置变得过时。那么映射实现的内部结构就会暴露出来。

m1 的 value 存储的是 Person 结构体的指针,其结构体占用的内存已经分配成功,且不会随着 hashmaps 的扩容而改变,所以 m1["xiyan"] 是可寻址的值。

5. 碎碎念

哎,今天真的是各种撕,快疯了的一天:

  • 女孩子太容易自责和自我否定。这个世界有时候是有点问题的,你要学会明辨是非。而不是人云亦云。大家都说女孩子要听话,要主内,问问你自己的内心,你真的愿意这样做吗?如果不愿意,就学会说 NO,爱自己就是做自己喜欢的事情,只要不违反法律和道德,与世界为敌又如何?
  • ♡ 盐于律己,甜以待人

6. 参考资料

Guess you like

Origin juejin.im/post/7031489121889550372