指针地址和指针类型
一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。当一个指针被定义后没有分配到任何变量时,它的默认值为 nil。指针变量通常缩写为 ptr。
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用在变量名前面添加&操作符(前缀)来获取变量的内存地址(取地址操作),格式如下:
ptr := &v // v 的类型为 T
其中 v 代表被取地址的变量,变量 v 的地址使用变量 ptr 进行接收,ptr 的类型为*T,称做 T 的指针类型,*代表指针。
package main
import (
"fmt"
)
func main() {
demo01()
}
func demo01() {
var cat int = 1
var str string = "banana"
fmt.Printf("%p %p", &cat, &str)
}
每个变量都拥有地址,指针的值就是地址
从指针获取指针指向的值
func demo02() {
// 准备一个字符串类型
var house = "Malibu Point 10880, 90265"
// 对字符串取地址, ptr类型为*string
ptr := &house
// 打印ptr的类型
fmt.Println()
// 打印ptr的指针地址
fmt.Printf("ptr type: %T\n", ptr) // ptr type: *string
// 对指针进行取值操作
fmt.Printf("address: %p\n", ptr) // address: 0xc00008a220
// 取值后的类型
value := *ptr
// 指针取值后就是指向变量的值
fmt.Printf("value type: %T\n", value) // value type: string
fmt.Printf("value: %s\n", value) // value: Malibu Point 10880, 90265
}
使用指针修改值
// 交换函数
func swap(a, b *int) {
// 取a指针的值, 赋给临时变量t
t := *a
// 取b指针的值, 赋给a指针指向的变量
*a = *b
// 将a指针的值赋给b指针指向的变量
*b = t
}
func demo03() {
// 准备两个变量, 赋值1和2
x, y := 1, 2
// 交换变量值,传递的是变量指针
swap(&x, &y)
// 输出变量值
fmt.Println(x, y) // 2,1
}
x, 与 y的值被交换了,由此可见,*
操作符的意义就是操作指针指向的变量:=
在左侧代表修改指向变量的值,右侧代表取指向变量的值
如果在 swap() 函数中交换操作的是指针值,会发生什么情况?
func swap2(a, b *int) {
a, b = b, a
}
func demo04() {
x, y := 1, 2
swap2(&x, &y)
fmt.Println(x, y)
}
// 1,2
x, y 并未被改变,因为实际上改变的是a,b这两个形参的值,并未与x,y关联
new() 函数创建指针
func demo05() {
str := new(string)
fmt.Println(str, *str)
*str = "hello go"
fmt.Println(str, *str)
}
// 0xc000010240
// 0xc000010240 hello go
有了之前的认识,这个new就非常好理解了,
- 先创建一个指针str,创建过程会分配内存,被创建的指针指向默认值
- 使用
*
操作符给指针所指的变量赋值