一、指针概述

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

认识指针地址和指针类型

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

  1. package main
  2. import "fmt"
  3. func main() {
  4. var count int = 5
  5. ptr := &count
  6. fmt.Printf("count的值=%d,内存地址是=%v\n",count,&count)
  7. fmt.Printf("ptr的值=%v,,ptr的类型=%T,内存地址是=%v\n",ptr,ptr,&ptr)
  8. }

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

  1. count的值=5,内存地址是=0xc00000a0a0
  2. ptr的值=0xc00000a0a0,,ptr的类型=*int,内存地址是=0xc000006028

提示:变量、指针和地址三者的关系是,每个变量和指针变量都拥有一个地址,变量的值是具体数据,但是指针的值是另一个变量的地址
** Go语言指针 - 图1

指针作用

节省内存空间,提升程序效率
间接访问和修改变量的值
image.png

二、指针操作

三、指针应用场景

指针定义

  1. package main
  2. import "fmt"
  3. func main() {
  4. var a int =2
  5. var b string ="pointer"
  6. var ptr1 *int=&a //声明指针变量ptr并初始化赋值&a
  7. ptr2 :=&b //ptr2存储的是b的地址,是指向*string的指针
  8. fmt.Printf("ptr1的数据类型:%T\n",ptr1) //打印ptr1的类型 *int
  9. fmt.Printf("ptr1的指针地址:%p\n",ptr1)//打印ptr2的指针地址
  10. fmt.Printf("ptr2的数据类型:%T\n",ptr2) //打印ptr2的类型 *string
  11. fmt.Printf("ptr2的指针地址:%p\n",ptr2)//打印ptr2的指针地址
  12. //对指针进行取值运算操作
  13. value:=*ptr1+3
  14. fmt.Printf("value的数据类型:%T\n",value)//取值运算后value的数据类型
  15. fmt.Printf("value的值:%d\n",value)//取值运算后value的值
  16. }
  17. //输出结果
  18. ptr的数据类型:*int
  19. ptr的指针地址:0xc0000a2058
  20. value的数据类型:int
  21. value的值:5

取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。

值传递和引用传递

除c和c++支持值传递和引用传递,其他编程语言如Java和python一般都支持引用传递。

  1. void pass_by_val(int a) {
  2. //拷贝main函数的a
  3. a++;
  4. }
  5. void pass_by_ref(int &a) {
  6. //引用传递
  7. a++;
  8. }
  9. int main() {
  10. int a=3;
  11. pass_by_val(a);
  12. printf("After pass_by_val: %d\n", a);
  13. pass_by_ref(a);
  14. printf("After pass_by_ref: %d\n", a);
  15. }
  16. /*输出结果*/
  17. After pass_by_val:3
  18. After pass_by_ref:4
  • pass_by_val函数值传递 :值传递是拷贝一份,不影响main函数的a
  • pass_by_ref函数引用传递 引用传递是不拷贝,被调的参数会被改变

值传递

image.png

引用传递

image.png
&a的地址被传递给了func函数里的指针变量pa。&a和pa同时指向变量a,因此在func函数里修改指针变量pa,都会影响外面变量a的值

cache传递

image.png

cache拷贝一份被传递给了func函数里的cachecache和func f里的cache同时指向data
**

使用指针修改值

  1. package main
  2. import "fmt"
  3. func swap(x,y *int){
  4. /*交换函数*/
  5. /*@:交换*x和*y的值**/
  6. *x,*y = *y,*x
  7. }
  8. func main() {
  9. x,y := 3,4
  10. swap(&x,&y)
  11. fmt.Println(x,y)
  12. }
  13. /*输出结果3,4*/

new() 函数创建指针

Go语言还提供了另外一种方法来创建指针变量,格式如下:
new(数据类型)
一般这样写:

  1. package main
  2. import "fmt"
  3. func main() {
  4. str :=new(string) //new函数创建指向string类型的指针
  5. *str="Go语言指针" //指针取值
  6. fmt.Printf("str指针变量的地址:%p\n",str)
  7. fmt.Printf("str指针变量的地址:%s\n",*str)
  8. }

new() 函数可以创建一个对应类型的指针,创建过程会分配内存,被创建的指针指向默认值。