【Go语言】Go语言中的指针

news2025/1/15 16:30:48

Go语言中的指针

变量的本质是对一块内存空间的命名,我们可以通过引用变量名来使用这块内存空间存储的值,而指针则是用来指向这些变量值所在内存地址的值。

注:变量值所在内存地址的值不等于该内存地址存储的变量值。

Go语言中,如果一个变量是指针类型的,可以用这个变量来存储指针类型的值。

以下是Go语言中,指针的简单使用:

a := 100
var ptr *int  // 声明指针类型
ptr = &a      // 初始化指针类型值为变量 a 
fmt.Println(ptr)
fmt.Println(*ptr)

如上代码中,变量 ptr 就是一个指针类型,表示指向存储 int 类型值的指针,ptr本身是一个内存地址,因此需要通过内存地址进行赋值(通过 &a 获取变量 a 所在的内存地址),赋值之后,可以通过 *ptr 获取指针指向内存地址所存储的变量值,这种操作称为“间接引用”。

1 指针类型的声明和初始化

指针变量在传值时之所以可以节省内存空间,是因为指针指向的内存地址的大小是固定的,在32位机器上占4个字节,在64位机器上占8个字节,这与指针指向内存地址存储的值类型无关。

var ptr *int
fmt.Println(ptr)
fmt.Println(*ptr)
​
a := 100
var ptr *int
ptr = &a
fmt.Println(ptr)
fmt.Println(*ptr)

指针被声明后,没有指向任何的内存空间,此时指针的值是零值nil,可以通过&变量名的方式获取变量对应的内存地址,再将其赋值给指针,这样就完成指针的初始化操作。

也能够通过 := 实现指针类型的初始化,代码如下所示:

b := 100
ptr2 := &b
fmt.Printf("%p\n", ptr2)
fmt.Printf("%d\n", *ptr2)

通过 := 进行指针的初始化,无需声明指针类型,底层会自动判断。

此外,也可以通过内置函数 new 声明指针:

ptr3 := new(int)
*ptr3 = 100

通过 new 初始化的指针,已经指向的内存地址,此时内存地址中存储的值是该指针类型的零值。

2 通过指针传值

通过指针传值能够节省内存空间,此外还能够在调用函数中实现对变量值的修改,因为直接修改了内存地址上存储的值,而不是值拷贝。

func swap(a, b int) {
    a, b = b, a
    fmt.Println(a, b)
}
func pointerSwap(a, b *int) {
    *a, *b = *b, *a
    fmt.Println(*a, *b)
}
​
// 值拷贝
func PointerValueCopyExample() {
    a := 10
    b := 20
    fmt.Println("直接进行值拷贝")
    swap(a, b)
    fmt.Println(a, b)
    fmt.Println("通过指针进行值交换")
    pointerSwap(&a, &b)
    fmt.Println(a, b)
}

如上运行结果,可以发现通过指针进行值交换,变量的值也会发生变化,这里是因为指针的交换是直接修改内存地址上存储的值,调用完交换函数后,对应的内存空间值也进行了交换,因此外部的指针指向变量地址存储的值也发生了变化。

3 unsafe.Pointer

unsafe.Pointer 是特别定义的一种指针类型,能够包含任意类型变量的地址,以下是Go语言官方的定义:

  • 任何类型的指针都可以被转化为 unsafe.Pointer;

  • unsafe.Pointer 可以被转化位任何类型的指针;

  • unintpr 可以被转化为 unsafe.Pointer;

  • unsafe.Pointer 可以被转化为 uintptr。

因此,unsafe.Pointer 可以在不同的指针类型之间做转化,从而可以表示任意可寻址的指针类型:

i := 10
var p *int = &i
var fp *float32 = (*float32)(unsafe.Pointer(p))
*fp = *fp * 10
fmt.Println(i)

如上代码中,首先是声明了一个int类型的指针 p 指向变量 i ,然后int类型的指针转化为unsafe.Pointer再转化为float32类型的指针,最终对p指向内存地址的变量进行修改,打印出来i的地址发生了变化。

unsafe.Pointer 是一个万能指针,可以在任何指针类型之间进行转化,绕过了Go语言的类型安全机制,因此是一个不安全的操作。

unsafe.Pointer 还可以与 uintptr 类型之间相互转化,uintptr 是 Go语言内置的可以用于存储指针的整型,而整型是可以进行运算的,因此将 unsafe.Pointer 转化为 uintptr 类型后,就可以让本不具备运算能力的指针具备了指针运算能力:

arr := [3]int{1, 2, 3}
ap := &arr
// unsafe.Sizeof 数组元素偏移量
// ap由unsafe.Pointer -> uintptr -> unsafe.Pointer
sp := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(ap)) + unsafe.Sizeof(arr[0])))
*sp += 3

这里,将arr数组的内存地址赋值给指针ap,通过unsafe.Pointer转化为uintptr类型,再加上数组中第一个元素的偏移量,就可以得到该数组中第二个元素的内存地址,最后通过unsafe.Pointer将其转化为int类型指针赋值给sp,修改sp指针指向内存地址的变量值。

通过如上操作,能够绕过Go语言中指针的安全限制,实现对指针的动态偏移和计算,但这样操作,如果数组发生了越界也不会报错,而是返回下一个内存地址的值,破坏了内存的安全限制,因此这个操作也是不安全的操作,尽量避免unsafe.Pointer的相关使用,必须使用时需要非常谨慎。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1476375.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3+vite+ts配置多个代理并解决报404问题

之前配置接口代理总是报404,明明接口地址是对的但还是报是因数写法不对;用了vue2中的写法 pathRewrite改为rewrite 根路径下创建env文件根据自己需要名命 .env.development文件内容 # just a flag ENVdevelopment# static前缀 VITE_APP_PUBLIC_PREFIX"" # 基础模块…

Dockerfile(2) - LABEL 指令详解

LABEL 可以为生成的镜像添加元数据标签信息&#xff0c;这些信息可以用来辅助过滤出特定镜像 LABEL <key><value> <key><value> <key><value> ... 栗子一 # key 加了 " LABEL "com.example.vendor""ACME Incorpor…

【活动】前端世界的“祖传代码”探秘:从古老魔法到现代重构

作为一名前端工程师&#xff0c;我时常在项目中邂逅那些被岁月打磨过的“祖传代码”。它们就像古老的魔法书页&#xff0c;用HTML标签堆砌起的城堡、CSS样式表中的炼金术&#xff0c;以及JavaScript早期版本中舞动的符咒。这些代码承载着先驱们的探索精神和独特智慧&#xff0c…

postman测试接口

1、postman测试接口 &#xff08;1&#xff09;首先安装postman 下载地址&#xff1a;Download Postman | Get Started for Free 选择对应版本下载&#xff0c;然后安装即可 &#xff08;2&#xff09;使用postman发送请求 比如以下这个请求例子&#xff1a; 使用postman发…

ArmV8架构

Armv8/armv9架构入门指南 — Armv8/armv9架构入门指南 v1.0 documentation 上面只是给了一个比较好的参考文档 其他内容待补充

Rocky Linux 运维工具 firewall-cmd

一、firewall-cmd​的简介 ​​firewall-cmd​是基于firewalld的防火墙管理工具。用户可以使用它来配置、监控和管理防火墙规则&#xff0c;包括开放端口、设置服务规则等。 二、firewall-cmd​​的参数说明 序号参数描述1​​–zone指定防火墙区域2–add-portxxx/tcp允许特定…

【查漏补缺你的Vue基础】Vue数据监听深度解析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

【笔记】:更方便的将一个List中的数据传入另一个List中

这里是 simpleInfoList 集合&#xff0c;记为集合A&#xff08;传值对象&#xff09; List<CourseSimpleInfoDTO> simpleInfoList courseClient.getSimpleInfoList(courseIds);if(simpleInfoListnull){throw new BizIllegalException("当前课程不存在!");}这…

深度学习与神经网络:构建智能系统的基石

一、引言 1、介绍深度学习和神经网络的背景和发展历程 深度学习和神经网络的背景和发展历程可以追溯到上世纪40年代和50年代的人工神经网络研究。当时&#xff0c;研究人员开始尝试模拟生物神经元之间的连接方式&#xff0c;构建了早期的神经网络模型。然而&#xff0c;由于计…

【Redis】深入理解 Redis 常用数据类型源码及底层实现(5.详解List数据结构)

本文是深入理解 Redis 常用数据类型源码及底层实现系列的第5篇&#xff5e;前4篇可移步(&#xffe3;∇&#xffe3;)/ 【Redis】深入理解 Redis 常用数据类型源码及底层实现&#xff08;1.结构与源码概述&#xff09;-CSDN博客 【Redis】深入理解 Redis 常用数据类型源码及底…

“智农”-大棚可视化

基于自主可控的数字孪生技术、物联网技术、大数据技术&#xff0c;构建全流程的新型农业一体化管理平台&#xff0c;围绕产运销管理全流程&#xff0c;实现生产->存储->包装->运输->销售的全链条管理。融合农业数据管理、农业数据预警显示、多维数据综合显示、农产…

IDEA基础——Maven配置tomcat

配置方案 一、配置maven-tomcat plugin插件&#xff08;只最高支持到tomcat 8&#xff09;~~1.添加镜像源&#xff0c;获取tomcat 8插件配置~~~~1.1 在pom.xml里先添加镜像源~~~~1.2 添加tomcat插件配置~~ 2. 添加tomact官方发布的插件配置&#xff08;无需添加镜像源&#xff…

从 0 到 1 搭建亿级商品 ES 搜索引擎

建设并维护一个亿级的搜索引擎并非易事&#xff0c;也不存在一劳永逸的最优治理方法。本文是在实践中不断学习和总结的成果&#xff0c;介绍了如何搭建一个可支持从千万级到亿级商品量级的搜索系统&#xff0c;并实现查询总 QPS 从百级增长到千级&#xff0c;写入总 QPS 从百级…

数据卷(Data Volumes) 自定义镜像(dockerfile)

目录 一. 数据卷&#xff08;Data Volumes&#xff09; 1.1 什么是数据卷 1.2 为什么需要数据卷 1.3 数据卷的作用 1.4 数据卷的使用 二. 自定义镜像&#xff08;dockerfile&#xff09; 2.1 什么是dockerfile 2.2 自定义centos 2.3 自定义tomcat 一. 数据卷&#xff08;Data…

【学习记录】HC32F460USB——U盘IAP升级app

从头开始&#xff0c;万物从解压开始 直奔猪蹄&#xff0c;找到usb下的工程文件 开始移植 主要移植IAP的boot和fatfs的文件系统&#xff0c;fatfs官网去下载ff15.0版本&#xff0c;目前用这个 放到项目里 添加到工程文件中 改引脚&#xff0c;给USB放电 编译&#xff0c;可以…

java自动化之自动化框架项目(第三天-测试数据注入到测试方法)

接第二天 1.实现目标 这里我们是数据驱动方式&#xff0c;把数据注入到测试方法&#xff0c;在测试方法中就可以获取对象中的数据。 2.注入测试数据 上一篇我们已经把用例数据封装到对象并放到list中&#xff0c;这里我们把用例对象list中的对象分别放到Object类型的一维数…

element-upload 文件上传和图片上传

文件上传 element-upload介绍实际上的文件上传代码前端java后端 补充 element-upload介绍 element-ui是一个很常用的文件上传组件&#xff0c;他包括但不局限于只上传图片&#xff0c;很多时候用于系统的头像修改就是用这个组件 在官网element-ui&#xff08;element-upload&a…

区块链游戏解说:什么是 Arcade Champion

作者&#xff1a;lesleyfootprint.network 编译&#xff1a;cicifootprint.network 数据源&#xff1a;Arcade Champion Dashboard 什么是 Arcade Champion Arcade Champion 代表了移动游戏世界的重大革新。它将经典街机游戏的怀旧与创新元素结合在一起&#xff0c;包括 NF…

《最新出炉》系列初窥篇-Python+Playwright自动化测试-33-处理https 安全问题或者非信任站点-上篇

1.简介 这一篇宏哥主要介绍playwright如何在IE、Chrome和Firefox三个浏览器上处理不信任证书的情况&#xff0c;我们知道&#xff0c;有些网站打开是弹窗&#xff0c;SSL证书不可信任&#xff0c;但是你可以点击高级选项&#xff0c;继续打开不安全的链接。举例来说&#xff0c…

redis中的分布式锁(setIfAbsent)(expire)

目录 应用场景 代码实例1&#xff1a; 代码实例2&#xff1a; setIfAbsent&#xff1a; expire&#xff1a; 举例说明&#xff1a; 代码实例3&#xff1a; 代码实例4&#xff1a; 还是一个同事问的一个问题&#xff0c;然后闲着没事就记录下来了。多人操作同一个保单&a…