指针类型

取址符:& 取值符: *

  1. var x = 10 // x 是整型变量
  2. //用 &x 取出 变量x 内存地址
  3. fmt.Println("x的内存地址:",&x) // x的内存地址: 0xc0000ae008
  4. // 定义 int 类型的指针变量
  5. var p *int
  6. p = &x // 将地址值赋值给的变量称为指针变量
  7. fmt.Println("p的值:",p) // p的值: 0xc0000ae008
  8. fmt.Println("p的地址:",&p) // p的地址: 0xc0000b2020
  9. fmt.Println("p的地址对应的值:",*p) // p的地址对应的值: 10

再次说明:

  1. //1. p 定义的是指针类型,也是一种数据类型,它存储的是内存地址
  2. //2. *数据类型: 这个数据类型是取决于你的内存地址里面放的值的数据类型。如果你的值是int类型,那么指针类型想拿这个值的地址,就要定义为 *int 类型,如果是你的值是 string 类型,那么就定义为*string,依次类推。
  3. //例如:int类型的
  4. var x int = 10 // x 是整型变量
  5. var p *int // 因为x的数据类型是int型,所以指针类型也是 int型
  6. p = &x
  7. fmt.Println(p, reflect.TypeOf(p)) // 0xc0000b0008 *int
  8. //例如:string类型
  9. s := "hello world"
  10. var p *string
  11. p = &s // 当然你嫌麻烦:直接写 p := &s

如图:
5.1、指针类型(核心类型) - 图1

内存中值变换

Go语言:当使用等号=将一个变量的值赋给另一个变量时,如 j = i ,实际上是在内存中将 i 的值进行了拷贝,可以通过 &i 获取变量 i 的内存地址。此时如果修改某个变量的值,不会影响另一个。

  1. var x int
  2. x = 10
  3. fmt.Println("x=10的内存地址:",&x) //x=10的内存地址: 0xc000018070
  4. x = 100
  5. fmt.Println("x=100的内存地址:",&x) // x=100的内存地址: 0xc000018070

从上面例子可以看出来,x 的变量一旦声明就在内存中占用一定的空间,不会因为值的变化,重新开辟空间,因为这个内存地址已经分配出来了,所以变量 x 的值只能在 int 的数据范围内:
5.1、指针类型(核心类型) - 图2
Python语言:内存地址重新指向,之前没有引用会垃圾回收站自动回收。
5.1、指针类型(核心类型) - 图3