Go语言之理解指针

作者: 有财君 | 来源:发表于2019-05-15 21:44 被阅读0次

    1. 说一下内存

    我们在编程的时候,实际上就是在操作内存,除非是进行IO操作写磁盘。其余的不管你是一半的变量还是Hibernate的Entity,都是在内存中闪转腾挪。

    我上学的时候,C语言课程是第一门编程语言课程,其中最难的部分就是指针,而指针就是直接操作内存的,所谓的C语言是最接近底层的语言,其中很重要的原因就是以为C语言让程序员可以直接去动内存。

    其实在很多年前,人们编程的时候绝对不像想在这么幸福,总是要直接操作内存的,而更久远一点的程序员们,要用汇编语言直接写指令,再久一点的程序员,就要在纸带上打孔,用01010这种二进制编码编程了。

    我说了这么多,其实想说的是,现在的很多编程语言比如Java,其实是对程序员隐藏了其内存操作的细节的。

    我们都知道Java有堆内存和栈内存,堆内存里是实际的对象,栈内存中的变量指向了对象,这里的指向,其实就是指针了。那么指向的是什么?有没有人曾经思考过这个问题,在内存中,如何快速的寻找一个值?

    答案自然是地址,只有用地址访问是最快的。

    内存结构

    如上图所示,如果有一种低级语言,也许是这样的:

    //我设计了一种运算符,[]内表示内存地址
    var [1] = 101
    

    这样就将内存地址1的块设置成了101。

    现在时代进步了,我们发明了变量这个概念,其实就是给内存地址起了名字:

    var a = 101
    

    此时变量a就是地址1的别名了,可以这么理解。

    2. 现在谈谈指针

    那么指针是什么?指针的值是一个变量的地址,一个指针只是值所保存的位置。

    下面写一段正确的Go代码,这段代码来自《The Go Programming Language》:

    x := 1
    p := &x
    //打印1
    fmt.Println(*p)
    *p = 2
    //打印2
    fmt.Println(x)
    

    这个时候画一个内存模型,应该是这样的:

    指针1

    &是取地址运算符,根据变量x,取到了相应的地址,此时如果打印p,得到的是一段类似这样的字符串:“0xc000016050”。

    接下来利用*p=2这个语句将指针指向的值改成2,画成图是这样的:

    修改指针值

    看看,利用指针我根本不需要去知道变量叫什么,只要改指针就可以了。

    下面再来一段代码,来源还是一样的:

    package main
    
    import "fmt"
    
    func incr(p *int) int {
        *p++
        return *p
    }
    
    func main() {
        v := 1
        incr(&v)
        fmt.Println(incr(&v))
    }
    

    这段代码比较迷惑的地方在于*p++,程序最终的返回结果是3,注意,这一句只是将指针p所指向的值进行了递增操作,但是并没有变更p本身,因此画出图来是这样的:

    修改指针值2

    3. 搞点事情

    如指针那张图,其实p也是内存中的一个地址,那么一定可以有一个指针指向它,这没毛病:

    v := 1
    p := &v
    q := &p
    

    此时的q就是一个指向指针的指针了。q得到的是p的地址,*q得到的就是p指向的值了。

    指向指针的指针在C语言里常常会用到,我现在初学Go,也不知道会不会频繁使用,反正有个印象就好了。

    相关文章

      网友评论

        本文标题:Go语言之理解指针

        本文链接:https://www.haomeiwen.com/subject/rigyaqtx.html