指针地址和指针类型

一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。当一个指针被定义后没有分配到任何变量时,它的默认值为 nil。指针变量通常缩写为 ptr。

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用在变量名前面添加&操作符(前缀)来获取变量的内存地址(取地址操作),格式如下:

ptr := &v // v 的类型为 T

其中 v 代表被取地址的变量,变量 v 的地址使用变量 ptr 进行接收,ptr 的类型为T,称做 T 的指针类型,代表指针。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. demo01()
  7. }
  8. func demo01() {
  9. var cat int = 1
  10. var str string = "banana"
  11. fmt.Printf("%p %p", &cat, &str)
  12. }

每个变量都拥有地址,指针的值就是地址

从指针获取指针指向的值

  1. func demo02() {
  2. // 准备一个字符串类型
  3. var house = "Malibu Point 10880, 90265"
  4. // 对字符串取地址, ptr类型为*string
  5. ptr := &house
  6. // 打印ptr的类型
  7. fmt.Println()
  8. // 打印ptr的指针地址
  9. fmt.Printf("ptr type: %T\n", ptr) // ptr type: *string
  10. // 对指针进行取值操作
  11. fmt.Printf("address: %p\n", ptr) // address: 0xc00008a220
  12. // 取值后的类型
  13. value := *ptr
  14. // 指针取值后就是指向变量的值
  15. fmt.Printf("value type: %T\n", value) // value type: string
  16. fmt.Printf("value: %s\n", value) // value: Malibu Point 10880, 90265
  17. }

使用指针修改值

  1. // 交换函数
  2. func swap(a, b *int) {
  3. // 取a指针的值, 赋给临时变量t
  4. t := *a
  5. // 取b指针的值, 赋给a指针指向的变量
  6. *a = *b
  7. // 将a指针的值赋给b指针指向的变量
  8. *b = t
  9. }
  10. func demo03() {
  11. // 准备两个变量, 赋值1和2
  12. x, y := 1, 2
  13. // 交换变量值,传递的是变量指针
  14. swap(&x, &y)
  15. // 输出变量值
  16. fmt.Println(x, y) // 2,1
  17. }

x, 与 y的值被交换了,由此可见,*操作符的意义就是操作指针指向的变量:=在左侧代表修改指向变量的值,右侧代表取指向变量的值
如果在 swap() 函数中交换操作的是指针值,会发生什么情况?

  1. func swap2(a, b *int) {
  2. a, b = b, a
  3. }
  4. func demo04() {
  5. x, y := 1, 2
  6. swap2(&x, &y)
  7. fmt.Println(x, y)
  8. }
  9. // 1,2

x, y 并未被改变,因为实际上改变的是a,b这两个形参的值,并未与x,y关联

new() 函数创建指针

  1. func demo05() {
  2. str := new(string)
  3. fmt.Println(str, *str)
  4. *str = "hello go"
  5. fmt.Println(str, *str)
  6. }
  7. // 0xc000010240
  8. // 0xc000010240 hello go

有了之前的认识,这个new就非常好理解了,

  1. 先创建一个指针str,创建过程会分配内存,被创建的指针指向默认值
  2. 使用*操作符给指针所指的变量赋值

空指针

当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。

  1. str := new(string)
  2. var ptr *int
  3. fmt.Println(str, *str, ptr)
  4. fmt.Println(str == nil, ptr == nil)

0xc00008c210 false true