1.1 指针的概念

指针式存储另一个变量的内存地址的变量。
变量是一种使用方便的占位符,用于引用计算机内存地址。
一个指针变量可以指向任何一个值的内存地址。

1.2获取变量的地址

Go语言中的取地址符与C语言取地址符一样是&,放到一个变量前使用就会返回相应变量的内存地址。

  1. arr := []int32{1, 2, 3}
  2. fmt.Println(arr)
  3. fmt.Println(&arr)
  4. fmt.Printf("变量的地址%x\n",&arr)
  5. a:=10
  6. fmt.Println(a)
  7. fmt.Println(&a)
  8. fmt.Printf("变量的地址%x\n",&a)
  9. /*
  10. [1 2 3]
  11. &[1 2 3]
  12. 变量的地址&[1 2 3]
  13. 10
  14. 0xc0000a20c0
  15. 变量的地址c0000a20c0
  16. */

1.3 声明指针

声明指针,*T是指针变量的类型,它指向T类型的值。

  1. var var_name * var-type
  2. var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。
  3. var ip *int /* 指向整型*/
  4. var fp *float32 /* 指向浮点型 */

示例:

  1. var a = 10 // 声明实际变量
  2. var ip *int // 声明指针变量
  3. ip = &a // 注意指针类型要与变量类型相同 int与int相同,诸如int与int16,int与int32不行
  4. fmt.Printf("a变量的地址是: %x\n", &a)
  5. fmt.Printf("ip变量的存储地址: %x\n", ip)
  6. fmt.Printf("*ip变量对应的值是: %d\n", *ip)
  7. /*
  8. a变量的地址是: c00000a100
  9. ip变量的存储地址: c00000a100
  10. *ip变量对应的值是: 10
  11. */

1.4 空指针

当一个指针被定义后,没有分配到任何变量时,它就是nil。nil指针也称为空指针。nil在概念上和其他语言的null、None、nil、NULL一样,都指代零值或者空值。一个指针变量统长缩写为ptr
空指针判断:

  1. if(ptr != nil) // ptr不是空指针
  2. if(ptr == nil) // ptr是空指针

示例:

  1. var ip *int // 定义指针,但是不分配任何变量
  2. fmt.Printf("ip变量的存储地址: %x\n", ip)
  3. if (ip == nil) {
  4. fmt.Println("为空指针")
  5. } else {
  6. fmt.Println("不是空指针")
  7. }
  8. /*
  9. ip变量的存储地址: 0
  10. 为空指针
  11. */

1.5 获取指针对应的值

获取一个指针对应的值。语法是 *指针变量
示例:

  1. var str = "127.0.0.1"
  2. ip := &str
  3. fmt.Println("ip的值是: ", ip)
  4. fmt.Println("ip所指向的值是: ", &ip)
  5. fmt.Println("str的类型是: ", reflect.TypeOf(str))
  6. fmt.Println("ip的类型是: ", reflect.TypeOf(ip))
  7. /*
  8. ip的值是: 0xc00002c1f0
  9. ip所指向的值是: 0xc000006030
  10. str的类型是: string
  11. ip的类型是: *string
  12. */

1.6 操作指针改变变量的数值

使用 *指针变量,获取值然后进行操作

  1. var a = 1
  2. b := &a
  3. fmt.Println("a的地址是:", b)
  4. fmt.Println("a的旧值是: ", *b)
  5. *b++
  6. fmt.Println("a的新值是: ", a)
  7. fmt.Println("a的新值是: ", *b)
  8. /*
  9. a的地址是: 0xc00000a100
  10. a的旧值是: 1
  11. a的新值是: 2
  12. a的新值是: 2
  13. */

将指向数组的指针作为参数传递给函数,进行修改
方法1:通过原始的方法进行修改

  1. originArr := []int{1, 1, 3, 4, 5}
  2. fmt.Println("originArr原始的值是: ", originArr)
  3. modify(&originArr, 1, 2) // 将索引为1位置上的值修改为2
  4. fmt.Println("originArr修改后的值是: ", originArr)
  5. /*通过原始方式进行修改*/
  6. func modify(arr *[]int, index int, newValue int) {
  7. (*arr)[index] = newValue
  8. }
  9. /*
  10. originArr原始的值是: [1 1 3 4 5]
  11. originArr修改后的值是: [1 2 3 4 5]
  12. */

方法2:使用切片进行修改

  1. originArr := []int{1, 1, 3, 4, 5}
  2. fmt.Println("originArr原始的值是: ", originArr)
  3. modifyBySplice(originArr[:], 1, 2) // 将索引为1位置上的值修改为2
  4. fmt.Println("originArr修改后的值是: ", originArr)
  5. /*通过切片进行修改*/
  6. func modifyBySplice(arr []int, index int, newValue int) {
  7. arr[index] = newValue
  8. }
  9. /*
  10. originArr原始的值是: [1 1 3 4 5]
  11. originArr修改后的值是: [1 2 3 4 5]
  12. */

1.7 指针作为函数参数

  1. a, b := 10, 11
  2. a, b = b, a
  3. fmt.Println("第一次交换后:", a, b)
  4. swap(&a, &b)
  5. fmt.Println("第二次交换后:", a, b)
  6. func swap(x *int, y *int) {
  7. var temp int
  8. temp = *x // 保存x地址的值
  9. *x = *y
  10. *y = temp
  11. }
  12. /*
  13. 第一次交换后: 11 10
  14. 第二次交换后: 10 11
  15. */