指针
指针也是一种类型,也可以
创建变量
,称之为指针变量
;指针变量的类型为
*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++)
}