Go 指针

39 阅读4分钟

指针

变量是一种占位符, 底层指向的是一个内存地址

&为取地址符, 如: addr为一个变量名 &addr 则为取出这个变量的地址

指针变量

存储的是一个地址, 指向的是变量的地址

&为取地址符 *是用来获取指针所指向地址的值

package main

import "fmt"

// 指针的使用
func main() {
	var addr1 int = 10
	// addr2 存储的是 addr1的地址, addr2也有自己的地址
	var addr2 = &addr1
	fmt.Println("addr1的地址: ", &addr1)   //  0xc0000200a8
	fmt.Println("addr2存储的地址: ", addr2)  //  0xc0000200a8
	fmt.Println("addr2自己的地址: ", &addr2) //  0xc000020028
	// 取出变量所指向地址中的值 *
	fmt.Println("addr2指向地址中的值", *addr2)
	// 可以通过操作 *addr2 达到修改 addr1值的效果 
	*addr2 = 100
	fmt.Println(addr1) // 100
}

指针的使用

package main

import "fmt"

func main() {
	// 声明 普通变量
	var a int = 100
	fmt.Printf("a的变量值:%d\n", a)   // 100
	fmt.Printf("a的变量地址:%p\n", &a) // 0xc0000a6058
	// 下声明一个指针变量, 指向a; 格式 var ptr *数据类型
	var ptr *int
	ptr = &a
	fmt.Printf("ptr 变量存储的指针地址:%p\n", ptr)       // 普通变量a的地址 0xc0000a6058
	fmt.Printf("ptr 变量的地址:%p\n", &ptr)          // ptr的地址 0xc0000ca020
	fmt.Printf("ptr 变量存储的指针地址所指向的值:%d\n", *ptr) // 其实就是a的值 100
	// 通过ptr改变a的值
	*ptr = 10
	fmt.Printf("a的值为:%d\n", a)       // 10
	fmt.Printf("*ptr的值为:%d\n", *ptr) // 10
	// 指针套娃 如何理解 这个类型是 *(*int) *表示指针类型变量 *后面跟的是 指针变量的数据类型
	var p **int
	p = &ptr
	fmt.Printf("p变量存储的指针的地址:%p\n", p)    // p存储的是变量ptr的变量地址 0xc0000ca020
	fmt.Printf("p变量的地址:%p\n", &p)        // 0xc0000ca028
	fmt.Printf("*p变量存储的内容(地址):%p\n", *p) // *p即ptr变量的所指向的地址(&a)~ 0xc0000a6058

}

数组指针

  • 数组指针: 是一个指针 指向一个数组
  • 指针数组: 是一个数组 保存的是指针
package main

import "fmt"

// 数组指针
func main() {
	// 创建数组
	arr1 := [4]int{2, 3, 4, 5}
	// 创建一个指针, 指向这个数组的地址, 后续可以通过指针来操作数组
	var p1 *[4]int
	p1 = &arr1
	fmt.Printf("p1指针的地址:%p\n", p1)      // p1指针的地址:0xc0000141e0
	fmt.Printf("p1变量的地址:%p\n", &p1)     // p1变量的地址:0xc00000a028
	fmt.Printf("p1变量的指向地址的值:%d\n", *p1) // p1变量的指向地址的值:[2 3 4 5]
	// 原生写法
	(*p1)[0] = 100
	fmt.Println("arr1:", arr1)    // [100 3 4 5]
	fmt.Println("p1指向地址的值:", *p1) // [100 3 4 5]
	// 语法糖: 因p1指向了arr1这个数组 直接用下表访问 操控数组 p1 = arr1
	// 指针指向谁,那么指针就可以代表谁
	p1[1] = 1000
	fmt.Println("arr1:", arr1)    // [100 1000 4 5]
	fmt.Println("p1指向地址的值:", *p1) // [100 1000 4 5]
}
package main

import "fmt"

// 指针数组
func main() {
	a, b, c, d := 1, 2, 3, 4
	arr1 := [4]*int{&a, &b, &c, &d}
	fmt.Println(arr1) // 这个数组存的都是变量的值
	// 通过指针修改a的值
	*arr1[0] = 200
	fmt.Println(a) // 200
	b = 300
	fmt.Println(*arr1[1]) // 300
}

指针函数

这是一个函数, 然后返回值是一个指针

package main

import "fmt"

// 指针函数
func main() {
	ptr := f() // 调用函数后, 可以得到一个指针类型的变量
	fmt.Println("ptr", ptr)
	fmt.Printf("ptr类型:%T\n", ptr)  // 函数类型(是一个指针) *[4]int
	fmt.Println("ptr的地址", &ptr)    // 0xc0000ca018
	fmt.Println("ptr地址中的值:", *ptr) // [1 2 3 4]
	// 使用方法
	fmt.Println(ptr[2]) // 3
	ptr[1] = 199
	fmt.Println(*ptr) // [1 199 3 4]
}

// 调用该函数后返回一个指针
func f() *[4]int {
	arr := [4]int{1, 2, 3, 4}
	return &arr
}

指针作为函数参数

指针作为函数的参数 (可以" 真正"改变值~) (可以解决 函数值传递)

package main

import "fmt"

func main() {
	// 值传递
	a := 1
	fmt.Println("a:", a)       // 1
	fmt.Println("a addr:", &a) // 0xc0000200a8

	fun(a)
	fmt.Println("a:", a)       // 1
	fmt.Println("a addr:", &a) // 0xc0000200a8
	fmt.Println("================")
	fun2(&a)
	fmt.Println("a:", a) // 100
	fmt.Println("a addr:", &a) // 0xc0000200a8 不难发现 从头到尾 都是在操作变量a(地址没有变化~)
}
func fun(ptr int) {
	fmt.Println("值传递")
	fmt.Println("ptr:", ptr) // 1
	ptr = 100                // 值传递中改变值 并不会传回去
}

// 指针为函数的参数
func fun2(ptr *int) {
	fmt.Println("指针做参数")
	fmt.Println("ptr:", ptr)           // 指针指向变量的地址 0xc0000200a8
	fmt.Println("ptr 指针的地址中的值:", *ptr) // 1
	*ptr = 100
}