指针 pointer
说明
说明
指针概念在go语言中被拆分为2个核心概念
- 类型指针,允许对这个指针类型的数据进行修改,传递数据使用指针,而无须拷贝数据,类型指针不能进行偏移和运算
- 切片,由指向起始元素的原始指针、元素数量和容量组成
定义方式
指针类型声明
说明
指针类型用 *
表示,指向某种类型的变量
var ptr *int // 指向一个 int 类型的指针
通过 new()
函数创建
new(类型)
package main
import "fmt"
func main() {
str := new(string)
*str = "我尼玛"
fmt.Println(*str)
}
输出
我尼玛
获取指针地址
说明
使用 &
操作符获取变量的地址
var a int = 10
var ptr *int = &a // 将 a 的地址赋值给 ptr
通过指针访问值
说明
使用 *
操作符(解引用)访问指针指向的变量
fmt.Println(*ptr) // 输出 a 的值,即 10
使用示例
指针地址和指针类型
说明
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置,go语言中使用 &
操作符放在变量前边对变量进行 取地址 操作,格式如下
ptr := &v // v的类型为T
其中 v
代表被取地址的变量,被取地址的 v
使用 ptr
变量进行接收,ptr
的类型就为 *T
,称作 T
的指针类型,*
代表指针
获取变量取地址后的指针值
package main
import "fmt"
func main() {
var cat int = 1
var str string = "hahaha"
fmt.Printf("%p %p", &cat, &str)
}
输出
说明
-
输出值在每次运行是不同的,代表
cat
和str
变量取地址后的指针值,指针值带有0x
的十六进制前缀 -
变量、指针和地址三者的关系是:每个变量都拥有地址,指针的值就是地址
0x14000098020 0x1400008e170
从指针获取指针指向的值
说明
在对普通变量使用 &
操作符取地址获得这个变量的指针后,可以对指针使用 *
操作,也就是指针取值
package main
import "fmt"
func main() {
// 准备一个字符串类型
var house = "北京市朝阳区将台路666号"
// 对字符串取地址,ptr类型为 *string
ptr := &house
// 打印ptr的类型
fmt.Printf("ptr type: %T\n", ptr)
// 打印ptr的指针地址
fmt.Printf("ptr address: %p\n", ptr)
// 对指针进行取值操作
value := *ptr
// 取值后的类型
fmt.Printf("value type: %T\n", value)
// 指针取值后就是指向变量的值
fmt.Printf("value: %s\n", value)
}
输出
说明
取地址操作符 &
和取值操作符 *
是一对互补操作符,&
取出地址,*
根据地址取出地址指向的值
变量,指针地址、指针变量、取地址、取值的相互关系和特性如下
- 对变量进行取地址(
&
)操作,可以获得这个变量的指针变量 - 指针变量的值就是指针地址
- 对指针变量进行取值(
*
)操作,可以获得指针变量指向的原变量的值
ptr type: *string
ptr address: 0x1400008e170
value type: string
value: 北京市朝阳区将台666号
使用指针修改值
注意
*
操作符作为右值时,意思是取指针的值;作为左值时,也就是放在赋值操作符的左边时,表示a指向的变量*
操作符的根本意义就是操作指针指向的变量- 当操作在右值时,就是取指向变量的值
- 当操作在左值时,就是将值设置给指向的变量
package main
import "fmt"
// 交换函数
func swap(a, b *int) {
// 取a指针的值,赋给临时变量t
t := *a
// 取b指针的值,赋给a指针指向的变量
*a = *b // 这里的 *a 是a指向的变量,不是取a指针的值
// 将a指针的值赋给b指针指向的变量
*b = t
}
func main() {
// 准备2个变量,赋值1和2
x, y := 1, 2
// 交换变量值
swap(&x, &y)
// 输出变量值
fmt.Println(x, y)
}
输出
2 1