Skip to content
On this page

指针

  • 指针也是一种类型,也可以创建变量,称之为指针变量;

  • 指针变量的类型为*Type,该指针指向一个Type类型的变量;

  • 指针存储某个实际变量的内存地址,通过记录某个变量的地址,从而间接的操作该变量;

指针操作符

  • &: 该操作符可以获取到一个变量的内存地址

  • *: 有两种含义:

    • 如果*操作符在赋值操作的左边(也就是等号(=)的左边),则表示该指针指向的变量
    • 如果*操作符在赋值操作的右边(也就是等号(=)的右边边),则表示该指针指向的变量的值,又称指针的解引用
Go
func p() {
	x := "蛇灵-血灵"
	y := &x
	
	// x => 蛇灵-血灵
	fmt.Println("x =>", x)
	// *y =>  蛇灵-血灵
	fmt.Println("*y => ", *y)
	// &x => 0x140000102d0
	fmt.Println("&x =>", &x)
	// y => 0x140000102d0
	fmt.Println("y =>", y)
}

创建指针

  • 先定义普通变量,再通过获取该普通变量的地址创建指针
Go
func createPointer() {
    // 定义普通变量 
	name := "张环"
	// 获取普通变量name的内存地址创建指针
	name1 := &name

	fmt.Println(name1) // 0x14000010270
}
  • 先创建指针并分配好内存,再给指针指向的内存地址写入对应的值
Go
func createPointer() {
    // 创建指针
	str := new(string)
	// 给指针指向的内存地址写入对应的值
	*str = "蛇灵"
	str1 := *str
	fmt.Println("str:", str, *str) // str: 0x14000010280 蛇灵
	fmt.Println("str1:", str1) // str1: 蛇灵
}
  • 先声明一个指针变量,再从其他变量获取内存地址给指针变量
Go
func createPointer() {
	// 定义普通变量
	title := "蛇灵-闪灵"
	// 定义指针变量
	var title1 *string
	// 将指针的值指向普通变量的内存地址
	title1 = &title
	fmt.Println(*title1, title) // 蛇灵-闪灵 蛇灵-闪灵
}

指针的类型

  • *Type中,Type指向变量值的数据类型,也就是对应的指针类型

示例

Go
func pointerType() {
	name := "魔灵"
	age := 22
	isBoss := false
	level := 32.86
	// type of &name is: *string
	fmt.Printf("type of &name is: %T \n", &name)
	// type of &age is: *int
	fmt.Printf("type of &age is: %T \n", &age)
	// type of &isBoss is: *bool
	fmt.Printf("type of &isBoss is: %T \n", &isBoss)
	// type of &level is: *float64
	fmt.Printf("type of &level is: %T \n", &level)
}

指针的零值

  • 指针声明后没有进行初始化,其默认值是nil

示例

Go
func zreoPointer() {
	name := "元芳"
	var mentor *string
	// 初始化未赋值时为: <nil>
	fmt.Println("初始化未赋值时为:", mentor)
	mentor = &name
	// 赋值之后为: 0x14000096230
	fmt.Println("赋值之后为:", mentor)
}

函数传递指针参数

  • changePointer函数传入的是指针参数,即内存地址,所以在函数内的修改是在内存地址上的修改,在函数执行后会对变量进行修改

示例

Go
func changePointer(age *int) {
  // 传递进来的age为: 0x1400001a128
	fmt.Println("传递进来的age为:", age)
	*age = 88
}

func testChangePointer() {
	age_one := 22
	age_two := &age_one
	// 执行changePointer函数之前age_two的值为: 22
	fmt.Println("执行changePointer函数之前age_two的值为:", *age_two)
	changePointer(age_two)
	// 执行changePointer函数之后age_two的值为: 88
	fmt.Println("执行changePointer函数之后age_two的值为:", *age_two)
	// 执行changePointer函数之后age_one的值为: 88
	// 由于修改了指指针指向的变量的值,所以原来的变量age_one也被修改了
	fmt.Println("执行changePointer函数之后age_one的值为:", age_one)
}

指针和切片

  • 因为数组是值类型,如果想在一个参数为数组的函数中对数组原始值进行修改是不行的,可以通过下面两种方式来做
    • 将该数组的切片当作参数传给函数(推荐的做法)
    • 将这个数组的指针当作参数传给函数

通过传入切片改变原数组的值

Go
func changeArray(value []string) {
	value[1] = "肖豹"
}

func testChangeArray() {
	names := [3]string{"张环", "李朗", "沈韬"}
	// 执行changeArray函数前names的值为: [张环 李朗 沈韬]
	fmt.Println("执行changeArray函数前names的值为:", names)
	changeArray(names[:])
	// 执行changeArray函数后names的值为: [张环 肖豹 沈韬]
	fmt.Println("执行changeArray函数后names的值为:", names)
}

通过传入数组的指针来修改原数组

Go
func changeArrayByPointer(value *[3]int) {
	(*value)[2] = 99
}

func testChangeArray() {
	ages := [3]int{22, 66, 88}
	// 执行changeArrayByPointer函数前ages的值为: [22 66 88]
	fmt.Println("执行changeArrayByPointer函数前ages的值为:", ages)
	changeArrayByPointer(&ages)
	// 执行changeArrayByPointer函数前ages的值为: [22 66 99]
	fmt.Println("执行changeArrayByPointer函数前ages的值为:", ages)
}

Go中不支持指针运算

Go
func pointerCalc() {
	name := "张环"
	colleague := &name
	// 报错 syntax error: unexpected ++ in argument list; possibly missing comma or )
	fmt.Println(colleague++)
}