这篇文章将为大家详细讲解有关golang中是否有指针,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
指针是一个代表着某个内存地址的值,这个内存地址往往是在内存中存储的另一个变量的值的起始位置。
<强>指针地址和变量空间强>
去语言保留了指针,但是与C语言指针有所不同。主要体现在:
- <李>
默认值:nil
李> <李>操作符<代码>和代码>取变量地址,<代码> * 代码>通过指针访问目标对象。
李> <李>不支持指针运算,不支持<代码>→代码>运算符,直接用<代码>。代码>访问目标成员。
李>先来看一段代码:
package 主要 import “fmt" func main () {, var x int =99 var p * int =,, x fmt.Println (p) }
当我们运行到<代码> var int x=99> 代码时,在内存中就会生成一个空间,这个空间我们给它起了个名字叫<代码> x> 代码,同时,它也有一个地址,例如:<代码> 0 xc00000a0c8> 代码,当我们想要使用这个空间时,我们可以用<>强劲地址强>去访问,也可以用我们给它起的<>强名字强> <代码> x 代码>去访问。
继续运行到<代码> var p * int=, x 代码>时,我们定义了一个<强>指针变量强> <代码> p> 代码,这个<代码> p> 代码就存储了变量x <代码> 代码>的地址。
所以,<强>指针就是地址,指针变量就是存储地址的变量。强>
接着,我们更改<代码> x> 代码的内容:
package 主要 import “fmt" func main (), { var x int =99 var p * int =,, x fmt.Println (p) x =100 fmt.Println (“x:,,,, x) fmt.Println (“* p:,,,, * p) * p =999 fmt.Println (“x:,,,, x) fmt.Println (“* p:,,,, * p) }
可以发现,x <代码> 代码>与<代码> * p 代码>的结果一样的。
其中,<代码> * p 代码>称为<代码>解引用> 代码或者<代码>间接引用代码>。
<代码> * p=999> 代码是通过借助x <代码> 代码>变量的地址,来操作x <代码> 代码>对应的空间。
<强>不管是x 强> <代码> 代码> <强>还是强> <代码> * p 代码> <>强,我们操作的都是同一个空间。强>
<强>栈帧的内存布局强>
首先,先来看一下内存布局图,以32位<代码> 代码>为例。
其中,<强>数据区>强保存的是初始化后的数据。
上面的代码都存储在<强>栈区>强。一般<代码>使()代码>或者<代码>新()代码>出来的都存储在堆区
接下来,我们来了解一个新的概念:<强>栈帧>强。
栈帧:用来给<强>函数>强运行提供内存空间,取内存于<代码>堆栈代码>上。
<>强当函数调用时,产生栈帧;函数调用结束,释放栈帧。强>
那么栈帧用来存放什么?
- <李>
<强>局部变量强>
李> <李><强>形参强>
李> <李>内存字段描述值
李>其中,<强>形参与局部变量存储地位等同强>
当我们的程序运行时,首先运行<代码>主要()代码>,这时就产生了一个栈帧。
当运行到<代码> var int x=99> 代码时,就会在栈帧里面产生一个空间。
同理,运行到<代码> var p * int=, x> 代码时也会在栈帧里产生一个空间。
如下图所示:
我们增加一个函数,再来研究一下。
如下图所示,当运行到<代码>测试(11)> 代码时,会继续产生一个栈帧,这时主要()<代码> 代码>产生的栈帧还没有结束。
golang中是否有指针