指针地址和指针类型
一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。当一个指针被定义后没有分配到任何变量时,它的默认值为 nil。指针变量通常缩写为 ptr。
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用在变量名前面添加&操作符(前缀)来获取变量的内存地址(取地址操作),格式如下:
ptr := &v // v 的类型为 T
其中 v 代表被取地址的变量,变量 v 的地址使用变量 ptr 进行接收,ptr 的类型为T,称做 T 的指针类型,代表指针。
package mainimport ("fmt")func main() {demo01()}func demo01() {var cat int = 1var str string = "banana"fmt.Printf("%p %p", &cat, &str)}
每个变量都拥有地址,指针的值就是地址
从指针获取指针指向的值
func demo02() {// 准备一个字符串类型var house = "Malibu Point 10880, 90265"// 对字符串取地址, ptr类型为*stringptr := &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: stringfmt.Printf("value: %s\n", value) // value: Malibu Point 10880, 90265}
使用指针修改值
// 交换函数func swap(a, b *int) {// 取a指针的值, 赋给临时变量tt := *a// 取b指针的值, 赋给a指针指向的变量*a = *b// 将a指针的值赋给b指针指向的变量*b = t}func demo03() {// 准备两个变量, 赋值1和2x, 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, 2swap2(&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,创建过程会分配内存,被创建的指针指向默认值
- 使用
*操作符给指针所指的变量赋值
空指针
当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。
str := new(string)var ptr *intfmt.Println(str, *str, ptr)fmt.Println(str == nil, ptr == nil)
0xc00008c210
false true
