指针到底是什么?

学习go后,经常见到一些名词:指针,指针类型,内存地址,引用类型
刚开始,确实比较迷糊,因为我是phper,php中没有这些概念。
查阅了一些资料后,理解了一些,这里分享一点点个人的理解。如果有错误的地方,欢迎各位golanger前辈批评哈。

什么是指针?

说白了,指针就是一个变量,只不过这个变量很特殊,它里面存放的是一个内存地址。
上面的说法其实不太准确,我们的一个数据放在内存中,可能会占用多个内存空间,也就是这个数据对应的地址可能不止一个,其实指针就是数据开始位置的地址,比如数据占用0x001, 0x002, 0x003 三块空间,那么此时指针就是0x001

什么是指针变量?

普通的变量,存放的是数据,那么如果我们想要存放一个其它变量的地址(指针)呢?
我们需要声明一个指针类型的变量,下面给个例子

var strPtr *string // 此时我们声明了一个指针变量strPtr,但是要注意,此时这个变量并没有初始化,也就是它里面并没有保存一个地址,因为go编译器并不知道要给哪个地址,所以 strPtr 等于 nil
fmt.Println(strPtr, strPtr == nil)  // <nil> true
// 当然了,我们可以用new函数,初始化指针变量,为其分配一个地址
var intPtr *int = new(int)
fmt.Println(intPtr, *intPtr, intPtr == nil)  // 0xc00000a0c8 0 false

什么是指针类型呢?

其实就是一种数据类型,比如有 *int, *string ,我们声明一个指针变量时,就需要指定一个指针所对应的变量数据类型了。

var intPtr *int  // 声明了一个int类型的指针变量

什么是内存地址呢?

我举个简单的例子说明一下,比如你去超市,会看到一排排的储物柜(内存),每个柜子都有一个编号(内存地址),现在你需要把你的一瓶水(数据)放进去,但我们想要使用这个柜子,得先申请,然后拿到一张凭证(声明的变量名称),否则我们就无法找到自己的柜子了。

所以内存地址,就是一个内存块的编号,我们用代码实现一下上述的过程:

var a string   // 申请一个储物柜,得到这个柜子的编号(变量a在内存中的地址)
a = "一瓶水"   // 将我的一瓶水(实际数据),放入这个柜子中

可见,数据本身跟地址的关系并不大,地址和变量才有关系
声明一个string类型的变量a,也就是在内存中,为a提供一个内存地址,至于里面放什么数据,只要是改类型范围内的,都可以。

比如,上面的柜子中,我可以放一瓶红茶,也可以放一瓶绿茶,但凭证和柜子的编号是不变的。

当然了,在同一次的运行中,地址不变,但是下一次再次运行,地址就可能会变了(也就是之前的柜子,已经被别人使用了)。

这里再讲一个知识点:

  1. 普通变量取地址,用 &

    a := 10
    fmt.Println(&a)
  2. 指针变量取地址

    a := 10
    ptr := &a  // 将变量a的地址,赋值给ptr这个指针变量
    fmt.Println(ptr) // 直接打印,它里面的数据就是一个地址,当然,肯定不是ptr这个变量的地址了,这里千万不要混淆了
  3. 取指针变量存放地址中的值 *

    fmt.Println(*a)
  4. 通过指针变量,修改值

     *ptr = 100
     fmt.Println(a, *ptr)

什么是引用

我们的slice,map就是引用,为什么?
因为它们存放的数据,不是数据本身,比如slice中,内部数据其实是这样的

type struct {
    引用的地址
    长度
    容量
}

所以我们普通的赋值一个slice,它还是引用的

slice1 := []int{1, 2, 3}
slice2 := slice1 // slice2切片里面,同样存放的依旧是slice1中的地址引用
slice2[0] = 100 // 此时slice1也会变,因为它们的数据本身,都是同一个内存地址,他们里面的数据,实际都是这个内存地址的一份引用
本作品采用《CC 协议》,转载必须注明作者和本文链接
六月的风
Junwind
讨论数量: 6

如果能丰富GO指针设计的思路拆解就更完美了。

1个月前 评论

PHP也有这个概念

1个月前 评论
Junwind (楼主) 1个月前
pop_hunter 3周前

go 没有引用的概念。“引用” 这个概念只不过是为了帮助我们理解而已。There Are No Reference Types in Go 实际上都是指针

1个月前 评论
长日将尽

引用的本质就是指针

1个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
躺平大叔 @ 躺平社区
文章
136
粉丝
15
喜欢
102
收藏
59
排名:274
访问:3.5 万
私信
所有博文
社区赞助商