当前位置: 首页 > news >正文

Go指针探秘:深入理解内存与安全性

目录

    • 1. 指针的基础
      • 1.1 什么是指针?
      • 1.2 内存地址与值的地址
        • 1.2.1 内存中的数据存储
        • 1.2.2 如何理解值的地址
    • 2. Go中的指针操作
      • 2.1 指针类型和值
        • 2.1.1 基本数据类型的指针
        • 2.1.2 复合数据类型的指针
      • 2.2 如何获取一个指针值
      • 2.3 指针(地址)解引用
    • 3. 深入理解指针
      • 3.1 我们为什么需要指针?
        • 3.1.1 提高程序性能
        • 3.1.2 动态数据结构
        • 3.1.3 与其他语言的比较
      • 3.2 关于"引用"这个术语
        • 3.2.1 引用与指针的区别
    • 4. Go指针的特性与限制
      • 4.1 Go指针的特性
        • 4.1.1 零值
        • 4.1.2 不支持指针算术
      • 4.2 Go指针的限制
        • 4.2.1 不支持指针到整数的转换
        • 4.2.2 不能获取内建数据类型的地址
        • 4.2.3 安全性
    • 5. 总结

Go指针为程序员提供了对内存的深入管理能力,同时确保了代码的安全性。本文深入探讨了Go指针的基础概念、操作、深层理解及其特性与限制。通过深入了解其设计哲学和应用,我们可以更好地利用Go的强大功能。

关注TechLead,分享互联网架构、云服务技术的全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收AI产品研发负责人。

file

1. 指针的基础

1.1 什么是指针?

指针是一种变量,其存储的是另一个变量的内存地址,而不是值本身。在很多编程语言中,当我们需要直接访问内存或者希望通过一个变量间接操作另一个变量时,会使用到指针。

示例:

var a int = 42
var p *int = &a
fmt.Println(p) // 打印变量a的内存地址

1.2 内存地址与值的地址

每一个变量都存储在内存中的一个位置上,这个位置被称为该变量的内存地址。而当我们谈论一个变量的地址时,我们实际上是在讨论这个内存地址。

1.2.1 内存中的数据存储

计算机的内存是按照字节(bytes)组织的,每个字节都有一个唯一的地址。一个变量占用的字节数取决于其类型,例如,一个 int 类型在64位系统上通常是8字节。

示例:

var x int64 = 123456789
fmt.Println(&x) // 打印变量x的内存地址
1.2.2 如何理解值的地址

当我们使用&操作符来获取一个变量的地址时,我们实际上获取的是指向该变量内存起始位置的指针。

示例:

var y string = "OpenAI"
fmt.Println(&y) // 打印变量y的内存地址

在上面的示例中,变量y存储了字符串"OpenAI",但&y给我们返回的是这个字符串存储在内存中的地址。


2. Go中的指针操作

2.1 指针类型和值

在Go中,每种数据类型都有与之关联的指针类型。指针类型的定义是前置一个*到原始数据类型前面。例如,int的指针类型是*int

2.1.1 基本数据类型的指针

示例:

var age int = 30
var agePointer *int = &agefmt.Println(age)        // 打印原始变量值:30
fmt.Println(agePointer) // 打印age变量的内存地址
2.1.2 复合数据类型的指针

Go中的复合数据类型(例如slices、maps、channels、arrays、structs)也有其对应的指针类型。

示例:

type Person struct {Name stringAge  int
}var person Person = Person{"Alice", 28}
var personPointer *Person = &personfmt.Println(person)          // 打印结构体值:{Alice 28}
fmt.Println(personPointer)   // 打印结构体的内存地址

2.2 如何获取一个指针值

要获取一个变量的指针值,可以使用&操作符。

示例:

var fruit string = "apple"
pointerToFruit := &fruitfmt.Println(fruit)           // 打印原始值:apple
fmt.Println(pointerToFruit)  // 打印fruit的内存地址

2.3 指针(地址)解引用

要获取指针指向的原始值,我们使用*操作符进行解引用。这允许我们间接地访问和修改指针指向的值。

示例:

var number int = 100
pointerToNumber := &numberfmt.Println(*pointerToNumber) // 通过解引用获取原始值:100// 修改指针指向的值
*pointerToNumber = 200
fmt.Println(number)           // 原始变量值被修改为:200

3. 深入理解指针

3.1 我们为什么需要指针?

指针在编程中是一个重要的工具,特别是在需要高性能、灵活性或者对内存使用有严格要求的场景中。

3.1.1 提高程序性能

指针可以减少数据复制的需要,从而提高程序的执行速度。

示例:

考虑一个场景,我们需要交换两个大的数据结构的值。

type LargeStruct struct {Data [1000]int
}func swapWithoutPointer(a, b LargeStruct) {a, b = b, a
}func swapWithPointer(a, b *LargeStruct) {*a, *b = *b, *a
}var x, y LargeStruct
// 使用指针交换
swapWithPointer(&x, &y)

在上面的例子中,使用指针的方法可以避免复制两次大的数据结构,从而更为高效。

3.1.2 动态数据结构

很多动态数据结构(如链表、树、图)都依赖于指针来实现。

示例:

type Node struct {Value intNext  *Node
}// 创建链表
first := Node{Value: 1}
second := Node{Value: 2}
third := Node{Value: 3}first.Next = &second
second.Next = &thirdfmt.Println(first.Value)  // 1
fmt.Println(first.Next.Value) // 2
3.1.3 与其他语言的比较

与其他一些语言(如C、C++)相比,Go在指针的使用上更为安全。Go不允许进行指针运算,这降低了因为错误操作而导致的程序错误的可能性。

3.2 关于"引用"这个术语

在其他一些编程语言中(如C++、Java),"引用"与"指针"是两个不同的概念,但在Go中,我们主要使用指针,而不是引用。

3.2.1 引用与指针的区别

在某些语言中,引用是一个别名,它表示某个变量。而指针则是一个变量,其值是另一个变量的地址。

示例: 在Go中,我们不使用引用,而是使用指针来实现间接引用。

var original int = 10
pointerToOriginal := &original*pointerToOriginal = 20fmt.Println(original) // 输出:20

在上述示例中,通过指针,我们修改了original变量的值。


4. Go指针的特性与限制

4.1 Go指针的特性

4.1.1 零值

在Go中,指针的零值是nil。这意味着如果你声明一个指针变量但没有明确初始化,它的值就是nil

示例:

var ptr *int
fmt.Println(ptr == nil) // 输出:true
4.1.2 不支持指针算术

与C和C++不同,Go不支持指针算术操作。这是为了确保更高的内存安全性。

示例:

在C或C++中,你可以做这样的操作:

int arr[10];
int *ptr = &arr[0];
ptr++;

但在Go中,类似的操作是不被允许的。

arr := [10]int{}
ptr := &arr[0]
// ptr++ // 这行会报错,因为Go不支持

4.2 Go指针的限制

4.2.1 不支持指针到整数的转换

在某些低级编程环境中,你可能需要将指针转换为整数进行某些操作,或者反之。但在Go中,这样的操作是不允许的,以确保程序的安全性和可读性。

4.2.2 不能获取内建数据类型的地址

在Go中,例如对于切片的元素或map的值,我们不能直接获取其地址。

示例:

m := map[string]int{"Alice": 25}
// ptr := &m["Alice"] // 这行会报错
4.2.3 安全性

Go的设计者们故意限制了指针的某些能力,以提高程序的安全性。例如,你不能在Go中进行指针算术,也不能随意地将指针与整数之间进行转换。


5. 总结

Go语言为现代编程提供了一种独特的途径。它不仅结合了经典的C风格语法,还引入了一系列新颖的设计哲学。这其中,Go对指针的处理尤为出色,它既维护了指针的功能性,又增强了代码的安全性。

深入的内存管理: Go语言通过指针让开发者有机会深入了解和管理内存。与直接操作值相比,指针为数据操作带来了更大的灵活性,特别是在处理大型数据结构或希望避免数据复制时。

安全性与简洁性的权衡: 通过消除指针算术和严格的类型限制,Go确保了程序员在操作指针时的安全性。这种设计选择可能限制了某些低级操作的能力,但它大大降低了因为误用指针而导致的程序错误的风险。

高级与低级的结合: 尽管Go提供了高级的数据结构如切片、映射等,但它仍然允许程序员通过指针进行低级的内存操作。这为开发者提供了无与伦比的灵活性,使他们既可以编写高性能的代码,又不失代码的可读性和可维护性。

关注TechLead,分享互联网架构、云服务技术的全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收AI产品研发负责人。

相关文章:

Go指针探秘:深入理解内存与安全性

目录 1. 指针的基础1.1 什么是指针?1.2 内存地址与值的地址1.2.1 内存中的数据存储1.2.2 如何理解值的地址 2. Go中的指针操作2.1 指针类型和值2.1.1 基本数据类型的指针2.1.2 复合数据类型的指针 2.2 如何获取一个指针值2.3 指针(地址)解引用…...

Oracle12c之Sqlplus命令行窗口基本使用

Oracle12c之Sqlplus命令行窗口基本使用 文章目录 Oracle12c之Sqlplus命令行窗口基本使用1. 连接1. 超级用户2. 普通用户1. 创建普通用2. 连接 2. 修改用户连接数1. 查看默认连接最多用户数1. PL/SQL developer中查看2. Sqlplus中查看 2. 查看目前已经连接的用户数3. 修改用户连…...

react和antd学习笔记

概论 react是前端框架,antd是组件库。前端框架和组件库的区别与联系 nodejs 脚本语言需要一个解析器才能运行,JavaScript是脚本语言,在不同的位置有不一样的解析器,如写入html的js语言,浏览器是它的解析器角色。而对…...

寒假作业2月5号

第四章 堆与拷贝构造函数 一 、程序阅读题 1、给出下面程序输出结果。 #include <iostream.h> class example {int a; public: example(int b5){ab;} void print(){aa1;cout <<a<<"";} void print()const {cout<<a<<endl;} …...

滑动窗口(一)

文章目录 Leetcode209. 长度最小的子数组题目解法一(暴力求解)&#xff08;超时&#xff09;解法二&#xff08;滑动窗口&#xff09; Leetcode3. 无重复字符的最长子串题目解法一&#xff08;暴力求解&#xff09;解法二&#xff08;滑动窗口&#xff09; Leetcode1004. 最大连…...

寒假 day1

1、请简述栈区和堆区的区别? 2、有一个整形数组:int arr[](数组的值由外部输入决定)&#xff0c;一个整型变量: x(也 由外部输入决定)。要求: 1)删除数组中与x的值相等的元素 2)不得创建新的数组 3)最多只允许使用单层循环 4)无需考虑超出新数组长度后面的元素&#xff0c;所以…...

DATAX改造支持geometry类型数据同步

数据库使用postgresql安装了postgis插件存储了geometry空间数据&#xff0c;想使用datax做数据同步&#xff0c;但datax本身不支持geometry类型数据&#xff0c;如何改造呢&#xff1f; 1.首先下载已改造支持geometry类型的datax引擎&#xff0c;下载地址 https://download.c…...

Vue中keep-alive的作用、原理及应用场景

在进行Vue开发的过程中&#xff0c;我们经常会遇到需要进行组件缓存的场景&#xff0c;这时候Vue提供的keep-alive组件就派上了用场。keep-alive组件是Vue内置的一个抽象组件&#xff0c;它可以将其包裹的组件进行缓存&#xff0c;提高组件的性能&#xff0c;同时也可以节省服务…...

SpringBoot集成Redisson实现限流(二)

1. 简介 Springboot集成Redisson默认的限流器为令牌桶型限流器&#xff0c;底层是通过lua脚本去实现的。 通过lua脚本我们可以去实现一个滑动窗口限流器&#xff0c;利用ZSET格式数据就可以轻松实现。 springboot集成Redisson就不做讲解&#xff0c;可以参考&#xff1a;sprin…...

【2024美赛E题】985博士解题思路分析(持续更新中)!

【2024美赛E题】985博士解题思路分析&#xff01; 加群可以享受定制等更多服务&#xff0c;或者搜索B站&#xff1a;数模洛凌寺 联络组织企鹅&#xff1a;936670395 以下是E题老师的解题思路&#xff08;企鹅内还会随时更新文档&#xff09;&#xff1a; 2024美赛E题思路详解…...

北朝隋唐文物展亮相广西,文物预防性保护网关保驾护航

一、霸府名都——太原博物馆收藏北朝隋朝文物展 2月1日&#xff0c;广西民族博物馆与太原博物馆携手&#xff0c;盛大开启“霸府名都——太原博物馆北朝隋文物展”。此次新春展览精选了北朝隋唐时期150多件晋阳文物珍品。依据“巍巍雄镇”“惊世古冢”“锦绣名都”三个单元&am…...

回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)

回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测&#xff08;SE注意力机制&#xff09; 目录 回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测&#xff08;SE注意力机制&…...

ubuntu离线安装k8s

目录 一、前期准备 二、安装前配置 三、安装docker 四、安装cri-dockerd 五、部署k8s master节点 六、整合kubectl与cri-dockerd 七、网络等插件安装 八、常见问题及解决方法 一、前期准备 ①ubuntu系统 本地已安装ubuntu系统&#xff0c;lsb_release -a命令查看版本信…...

学成在线:媒体资源管理系统(MAM)

媒体资源管理系统(MAM) 媒体资源管理系统(Media Asset Management)是建立在多媒体、网络、数据库和数字存储等先进技术基础上的一个对各种媒体及内容进行数字化存储、管理以及应用的总体解决方案,可以满足媒体资源拥有者收集、保存、查找、编辑、发布各种信息的要求,为媒体资源…...

18个8年以上服务器开发经验的面试题(2)

目录 1.问:如何设计一个系统来确保在可能出现网络分区和故障的分布式环境中的数据一致性?...

【SpringBoot】applicationContext.getBeansOfType(class)获取某一接口所有实现类,应用于策略模式

一、问题的提出 在实际工作中&#xff0c;我们经常会遇到一个接口及多个实现类的情况&#xff0c;并且在不同的条件下会使用不同的实现类。 二、应用场景 springboot 项目中通过 ApplicationContext.getBeansOfType(class) 获取某一接口的所有实现类&#xff0c;并通过枚举完…...

AJAX-入门

定义 概念&#xff1a;AJAX是浏览器与服务器进行数据通信的技术 使用 1.先使用axios库&#xff0c;与服务器进行数据通信 1&#xff09;基于XMLHttpRequest封装、代码简单、月下载量在14亿次 2&#xff09;Vue、React项目中都会用到axios 2.再学习XMLHttpRequest对象的使用…...

学术写作|第二篇论文写作记录|GPT4论文润色Prompt

本文目录 写作时间安排如何写出初稿?找谁修改?1. 找AI修改2. 找师姐、师兄、老师、同行/外行修改论文修改意见集锦(反复观看)最好用的GPT4指令禁止转载,未经允许的任何引用。 写作时间安排 第二篇工作的idea去年就想出来了,一直被其他事情干扰,错过了N个会议… 在寒假…...

力扣热门100题刷题笔记 - 10. 正则表达式匹配

力扣热门100题 - 10. 正则表达式匹配 题目链接&#xff1a;10. 正则表达式匹配 题目描述&#xff1a; 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符 * 匹配零个或多个前面的那一个元素 所谓匹配&#xff…...

4.0 HDFS 配置与使用

之前提到过的 Hadoop 三种模式&#xff1a;单机模式、伪集群模式和集群模式。 单机模式&#xff1a;Hadoop 仅作为库存在&#xff0c;可以在单计算机上执行 MapReduce 任务&#xff0c;仅用于开发者搭建学习和试验环境。 伪集群模式&#xff1a;此模式 Hadoop 将以守护进程的…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

Redis上篇--知识点总结

Redis上篇–解析 本文大部分知识整理自网上&#xff0c;在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库&#xff0c;Redis 的键值对中的 key 就是字符串对象&#xff0c;而 val…...