广告
返回顶部
首页 > 资讯 > 后端开发 > GO >golang中是否有指针
  • 860
分享到

golang中是否有指针

2023-06-14 06:06:13 860人浏览 独家记忆
摘要

这篇文章将为大家详细讲解有关golang中是否有指针,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。指针是一个代表着某个内存地址的值,这个内存地址往往是在内存中存储的另一个变量的值的起始位置。

这篇文章将为大家详细讲解有关golang中是否有指针,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

指针是一个代表着某个内存地址的值,这个内存地址往往是在内存中存储的另一个变量的值的起始位置。

指针地址和变量空间

Go语言保留了指针, 但是与C语言指针有所不同. 主要体现在:

  • 默认值:nil

  • 操作符 & 取变量地址, * 通过指针访问目标对象。

  • 不支持指针运算,不支持 -> 运算符,直接用 . 访问目标成员。

先来看一段代码:

package mainimport "fmt"func main(){ var x int = 99var p *int = &xfmt.Println(p)}

当我们运行到 var x int = 99 时,在内存中就会生成一个空间,这个空间我们给它起了个名字叫 x,同时, 它也有一个地址,例如: 0xc00000a0c8,当我们想要使用这个空间时,我们可以用地址去访问,也可以用我们给它起的名字 x 去访问.

继续运行到 var p *int = &x 时,我们定义了一个指针变量 p,这个 p 就存储了变量 x 的地址.

所以,指针就是地址,指针变量就是存储地址的变量。

接着,我们更改 x 的内容:

package mainimport "fmt"func main() {var x int = 99var p *int = &xfmt.Println(p)x = 100fmt.Println("x: ", x)fmt.Println("*p: ", *p)*p = 999fmt.Println("x: ", x)fmt.Println("*p: ", *p)}

可以发现, x*p 的结果一样的。

其中, *p 称为 解引用 或者 间接引用

*p = 999 是通过借助 x 变量的地址,来操作 x 对应的空间。

不管是 x 还是 *p , 我们操作的都是同一个空间。

栈帧的内存布局

首先, 先来看一下内存布局图, 以 32位 为例.

golang中是否有指针

其中, 数据区保存的是初始化后的数据.

上面的代码都存储在栈区. 一般 make() 或者 new() 出来的都存储在堆区

接下来, 我们来了解一个新的概念: 栈帧.

栈帧: 用来给函数运行提供内存空间, 取内存于 stack 上.

当函数调用时, 产生栈帧; 函数调用结束, 释放栈帧.

那么栈帧用来存放什么?

  • 局部变量

  • 形参

  • 内存字段描述值

其中, 形参与局部变量存储地位等同

当我们的程序运行时, 首先运行 main(), 这时就产生了一个栈帧.

当运行到 var x int = 99 时, 就会在栈帧里面产生一个空间.

同理, 运行到 var p *int = &x 时也会在栈帧里产生一个空间.

如下图所示:

golang中是否有指针

我们增加一个函数, 再来研究一下.

package mainimport "fmt"func test(m int){var y int = 66y += m}func main() {var x int = 99var p *int = &xfmt.Println(p)x = 100fmt.Println("x: ", x)fmt.Println("*p: ", *p)test(11)*p = 999fmt.Println("x: ", x)fmt.Println("*p: ", *p)}

如下图所示, 当运行到 test(11) 时, 会继续产生一个栈帧, 这时 main() 产生的栈帧还没有结束.

golang中是否有指针

test() 运行完毕时, 就会释放掉这个栈帧.

golang中是否有指针

空指针与野指针

空指针: 未被初始化的指针.

var p *int

这时如果我们想要对其取值操作 *p, 会报错.

野指针: 被一片无效的地址空间初始化.

var p *int = 0xc00000a0c8

指针变量的内存存储

表达式 new(T) 将创建一个 T 类型的匿名变量, 所做的是为 T 类型的新值分配并清零一块内存空间, 然后将这块内存空间的地址作为结果返回, 而这个结果就是指向这个新的 T 类型值的指针值, 返回的指针类型为 *T.

new() 创建的内存空间位于heap上, 空间的默认值为数据类型的默认值. 如: p := new(int)*p0.

package mainimport "fmt"func main(){p := new(int)fmt.Println(p)fmt.Println(*p)}

这时 p 就不再是空指针或者野指针.

我们只需使用 new() 函数, 无需担心其内存的生命周期或者怎样将其删除, 因为Go语言的内存管理系统会帮我们打理一切.

接着我们改一下*p的值:

package mainimport "fmt"func main(){p := new(int)*p = 1000fmt.Println(p)fmt.Println(*p)}

这个时候注意了, *p = 1000 中的 *pfmt.Println(*p) 中的 *p 是一样的吗?

大家先思考一下, 然后先来看一个简单的例子:

var x int = 10var y int = 20x = y

好, 大家思考一下上面代码中, var y int = 20 中的 yx = y 中的 y 一样不一样?

结论: 不一样

var y int = 20 中的 y 代表的是内存空间, 我们一般把这样的称之为左值; 而 x = y 中的 y 代表的是内存空间中的内容, 我们一般称之为右值.

x = y 表示的是把 y 对应的内存空间的内容写到x内存空间中.

等号左边的变量代表变量所指向的内存空间, 相当于操作.

等号右边的变量代表变量内存空间存储的数据值, 相当于操作.

在了解了这个之后, 我们再来看一下之前的代码.

p := new(int)*p = 1000fmt.Println(*p)

所以, *p = 1000 的意思是把1000写到 *p 的内存中去;

fmt.Println(*p) 是把 *p的内存空间中存储的数据值打印出来.

所以这两者是不一样的.

如果我们不在main()创建会怎样?

func foo() {p := new(int)*p = 1000}

我们上面已经说过了, 当运行 foo() 时会产生一个栈帧, 运行结束, 释放栈帧.

那么这个时候, p 还在不在?

p 在哪? 栈帧是在栈上, 而 p 因为是 new() 生成的, 所以在 上. 所以, p 没有消失, p 对应的内存值也没有消失, 所以利用这个我们可以实现传地址.

对于堆区, 我们通常认为它是无限的. 但是无限的前提是必须申请完使用, 使用完后立即释放.

函数的传参

明白了上面的内容, 我们再去了解指针作为函数参数就会容易很多.

传地址(引用): 将地址值作为函数参数传递.

传值(数据): 将实参的值拷贝一份给形参.

无论是传地址还是传值, 都是实参将自己的值拷贝一份给形参.只不过这个值有可能是地址, 有可能是数据.

所以, 函数传参永远都是值传递.

了解了概念之后, 我们来看一个经典的例子:

package mainimport "fmt"func swap(x, y int){x, y = y, xfmt.Println("swap  x: ", x, "y: ", y)}func main(){x, y := 10, 20swap(x, y)fmt.Println("main  x: ", x, "y: ", y)}

结果:

swap  x:  20 y:  10main  x:  10 y:  20

我们先来简单分析一下为什么不一样.

首先当运行 main() 时, 系统在栈区产生一个栈帧, 该栈帧里有 xy 两个变量.

当运行 swap() 时, 系统在栈区产生一个栈帧, 该栈帧里面有 xy 两个变量.

运行 x, y = y, x 后, 交换 swap() 产生的栈帧里的 xy 值. 这时 main() 里的 xy 没有变.

swap() 运行完毕后, 对应的栈帧释放, 栈帧里的x y 值也随之消失.

所以, 当运行 fmt.Println("main x: ", x, "y: ", y) 这句话时, 其值依然没有变.

接下来我们看一下参数为地址值时的情况.

传地址的核心思想是: 在自己的栈帧空间中修改其它栈帧空间中的值.

而传值的思想是: 在自己的栈帧空间中修改自己栈帧空间中的值.

注意理解其中的差别.

继续看以下这段代码:

package mainimport "fmt"func swap2(a, b *int){*a, *b = *b, *a}func main(){x, y := 10, 20swap(x, y)fmt.Println("main  x: ", x, "y: ", y)}

结果:

main  x:  20 y:  10

这里并没有违反 函数传参永远都是值传递 这句话, 只不过这个时候这个值为地址值.

这个时候, xy 的值就完成了交换.

我们来分析一下这个过程.

首先运行 main() 后创建一个栈帧, 里面有 x y 两个变量.

运行 swap2() 时, 同样创建一个栈帧, 里面有 a b 两个变量.

注意这个时候, a b 中存储的值是 x y 的地址.

当运行到 *a, *b = *b, *a 时, 左边的 *a 代表的是 x 的内存地址, 右边的 *b 代表的是 y 的内存地址中的内容. 所以这个时候, main() 中的 x 就被替换掉了.

所以, 这是在 swap2() 中操作 main() 里的变量值.

现在 swap2() 再释放也没有关系了, 因为 main() 里的值已经被改了.

关于golang中是否有指针就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

您可能感兴趣的文档:

--结束END--

本文标题: golang中是否有指针

本文链接: https://www.lsjlt.com/news/268543.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • golang中是否有指针
    这篇文章将为大家详细讲解有关golang中是否有指针,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。指针是一个代表着某个内存地址的值,这个内存地址往往是在内存中存储的另一个变量的值的起始位置。...
    99+
    2023-06-14
  • golang有指针么
    本教程操作环境:windows7系统、GO 1.18版本、Dell G3电脑。与 Java 和 .NET 等编程语言不同,Go语言为程序员提供了控制数据结构指针的能力,但是,并不能进行指针运算。Go语言允许你控制特定集合的数据结构、分配的数...
    99+
    2022-11-23
    Golang go语言 Go
  • golang有没有指针
    这篇文章主要介绍了golang有没有指针的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇golang有没有指针文章都会有所收获,下面我们一起来看看吧。golang有指针。Go语言为程序员提供了控制数据结构指针的能...
    99+
    2023-07-04
  • Golang中有指针吗?怎么用?
    Golang是一门现代化的编程语言,简称Go,它采用了静态类型、并发性强、效率高、开发效率高的特点,成为了现代Web应用开发中的一个重要语言,吸引了许多程序员的关注。在Golang中,指针是一种非常重要的数据类型。指针可以存储变量的内存地址...
    99+
    2023-05-14
  • golang指针用法是什么
    golang指针用法有:1、获取变量的地址,通过在变量名前加上&符号可以获取变量的内存地址;2、访问指针指向的值,通过在指针变量前加上*符号可以访问指针指向的值;3、创建指针变量,使用new关键字创建一个指定类型的零值指针变量;4、传递指针...
    99+
    2023-12-12
    Golang
  • golang中方法receiver为指针和不为指针的区别有哪些
    这篇文章将为大家详细讲解有关golang中方法receiver为指针和不为指针的区别有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。golang中方法的receiver为指针和不为指针的区别前言最近看...
    99+
    2023-06-15
  • golang中方法的receiver为指针和不为指针的有哪些区别
    这篇文章给大家分享的是有关golang中方法的receiver为指针和不为指针的有哪些区别的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。什么是golanggolang 是Google开发的一种静态强类型、编译型、...
    99+
    2023-06-14
  • Golang中指针的使用详解
    目录1.概念2.指针定义与空指针3.指针赋值与取值4.切片指针5.指针的指针1.概念 指针:指向内存地址的变量,指针用来存储变量的内存地址 Go 语言定义变量必须声明数据类型,因为不...
    99+
    2023-05-18
    Golang指针 Go指针类型
  • golang指针转换的方法是什么
    这篇文章主要介绍了golang指针转换的方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇golang指针转换的方法是什么文章都会有所收获,下面我们一起来看看吧。一、指针的基本使用在Golang中,指针是...
    99+
    2023-07-05
  • javascript中有没有指针
    本篇内容介绍了“javascript中有没有指针”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2022-10-19
  • golang是否有抽象类
    golang没有抽象类。golang并不是面向对象(OOP)语言,没有类和继承的概念,也没有抽象类的概念;但golang中有结构体(struct)和接口(interface),可以通过struct和interface的组合来间接实现面向对象...
    99+
    2023-05-14
    抽象类 go语言 Golang
  • php中数组指针指的是什么
    这篇“php中数组指针指的是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“php中数组指针指的是什么”文章吧。在php中...
    99+
    2023-07-02
  • C++中指针常量与常量指针的区别是什么
    在C++中,指针常量和常量指针是不同的概念。1. 指针常量(Pointer to constant):指针本身是一个常量,即指针的值...
    99+
    2023-08-16
    C++
  • PHP5中指针有哪些类型
    PHP5中指针有哪些类型,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。首先我们来理解三个关键字: this,self,parent,从字面上比较好理解,是指这,自己,父亲,...
    99+
    2023-06-17
  • php中什么是数组指针
    在php中,数组指针是数组内部的组织机制,每个数组都有一个内部的指针指向它“当前的”单元(元素),这个指针最初指向的是当前数组中的第一个单元;通过移动或改变指针的位置,可以访问数组中的任意元素。对于数组指针的控制PHP提供了多个内置函数:c...
    99+
    2022-06-28
    php php数组
  • C语言中指针常量和常量指针的区别是什么
    这篇文章主要介绍了C语言中指针常量和常量指针的区别是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言中指针常量和常量指针的区别是什么文章都会有所收获,下面我们一起来看看吧。在面试中我们经常会被面试官问到...
    99+
    2023-06-26
  • C++中的this指针有什么用
    这篇文章主要介绍“C++中的this指针有什么用”,在日常操作中,相信很多人在C++中的this指针有什么用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++中的this指针有什么用”的疑惑有所帮助!接下来...
    99+
    2023-06-17
  • C++中函数指针有什么用
    这篇文章主要为大家展示了“C++中函数指针有什么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C++中函数指针有什么用”这篇文章吧。1、函数指针函数指针顾名思义,就是指向函数的指针。和数据类似...
    99+
    2023-06-25
  • C语言中指针有什么用
    这篇文章主要介绍C语言中指针有什么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!(壹)  敢问指针为何物 1.1  指针的概念在计算机科学中,指针(Pointer)是编程语言中的一个对...
    99+
    2023-06-29
  • golang如何判断是否以指定字符结尾
    这篇文章主要讲解了“golang如何判断是否以指定字符结尾”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“golang如何判断是否以指定字符结尾”吧!在golang中,可以使用strings包...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作