Go 学习笔记(13):指针

简介

var a int32 = 10
复制代码

如上,a 就是一个变量,那么我们为什么需要变量呢?因为在编程中,我们要操作的数据存放在内存中,如果直接操作内存地址,可读性非常差,所以需要用标识符来表示相应的内存地址,也就是变量,通过操作变量来操作其对应的内存。

简单来说,指针就是变量对应的内存地址。不是每个值都有内存地址,但每个变量必然有对应的内存地址。通过指针,我们可以直接操作变量的值,而不需要知道变量的名字。

可以将指针理解为内存地址,但严格上讲并不准确。应该这么说:对于变量 aa 的指针保存了 a 的内存地址;对于整型 int,其指针类型 *int 是指向 int 类型的指针。

&*

取址符 & 用来获取变量的内存地址;而 * 作用在指针上时是获取该指针指向的值,出现在类型前面时表示的是该类型的指针类型。举例:

a := 10            // 10
p := &a            // 0xc00000a0a8
fmt.Println(*p)    // 10

var p2 *int
fmt.Printf("%p %v", p2, p2)    // 0x0 <nil>

p2 = &a            // 0xc00000a0a8
*p2 = 20           // 0xc00000a0a8
fmt.Println(a)     // 20,改变了原来的值,详细请见下面的章节

// 对于变量 var,var == *(&var) 是正确的
b := 1
fmt.Println(b == *(&b))  // true
复制代码

上面也可以看出,指针类型的零值nil

另外,var ptr*int 也是有效的(ptr* 之间没有空格),但请尽量不要用这种语法,容易被误认为是乘法表达式。

指针的格式化标识符为 %p

深入

图解例子:

var a int = 1
ptr := &a

fmt.Println(a)    // 1
fmt.Println(ptr)  // 0xc420018100
复制代码

简单理解,变量 a 的值 1 存储在内存块 0xc420018100,指针 ptr 直接指向内存地址,当我们操作 ptr 时,a 就自然变化了:

*ptr = 3
fmt.Println(a)    // 3
复制代码

比较

  • 任何类型的指针的零值都是 nil
  • 不同的指针类型不能比较,即便都是 nil
  • 指向同一个变量或都是 nil 时相等
a := 1
b := 2
s := "abc"

var ptr1 *int
var ptr2 *int
var ptr3 *string

&a == &s    // invalid operation: &a == &s (mismatched types *int and *string)
&a == &b    // false

ptr1 == ptr2  // true 
ptr1 == ptr3  // invalid operation: ptr1 == ptr3 (mismatched types *int and *string)
ptr1 == &a    // false

ptr1 = &a
ptr1 == &a    // true
复制代码

注意

不能对常量或文字取址:

&10     // cannot take the address of 10
&"abc"  // cannot take the address of "abc"
复制代码

Go 中的指针是内存安全的,更类似于 JavaC# 等中的引用Python 中的可变类型。

应用

传递一个变量的引用(即传递指针)的性能是非常高的,只占用了几个字节,这在函数的参数传递中很有用处。当程序中需要占大量的内存,或者有很多的变量,使用指针能有效的提高效率,请见后续的函数中的“引用传递”。

转载于:https://juejin.im/post/5c7f1b62518825470368e266

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值