指针
变量是一种占位符, 底层指向的是一个内存地址
&为取地址符, 如: 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
}