【Go语言】深入解读Go语言中的指针,助你拨开迷雾见月明

在这里插入图片描述

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。

所属的专栏:Go语言开发零基础到高阶实战
景天的主页:景天科技苑

在这里插入图片描述

文章目录

  • Go语言中的指针
    • 一、指针的基本概念
      • 1. 获取变量的地址
      • 2. 访问指针指向的值
    • 二、指针的基本用法
      • 1. 定义指针
      • 2. 使用`new`函数创建指针
      • 3. 指针作为函数参数
      • 4. 指针作为函数返回值
      • 5. 空指针检查
    • 三、指针的高级用法
      • 1. 指针数组和指针切片
        • 指针数组
        • 指针切片
      • 2. 数组指针
      • 3. 指针和切片
      • 4. 指针和方法
      • 5. 接口中的指针
      • 6. 指针的指针
    • 四、总结

Go语言中的指针

在Go语言中,指针是一种特殊的变量类型,它用于存储变量的内存地址。通过指针,程序可以直接访问和修改变量的值,这在处理大型数据结构、优化内存使用和提高程序性能时非常有用。本文将结合具体案例,详细讲解Go语言中指针的用法,包括定义指针、使用指针访问和修改变量值、指针作为函数参数和返回值、指针数组和切片、结构体指针、空指针检查等。

一、指针的基本概念

指针是指向内存地址的变量。在Go语言中,使用*操作符来声明一个指针变量。例如:

var p *int // 声明一个指向int型变量的指针

这里p是一个整型指针,它存储的是一个整型变量的内存地址。

1. 获取变量的地址

通过在变量名前加上&符号,可以获取变量的内存地址。例如:

var x int = 10
var p *int = &x // p存储了x的地址

2. 访问指针指向的值

通过在指针变量前加上*符号,可以访问指针指向的值。例如:

fmt.Println(*p) // 输出指针p指向的值,即变量x的值

二、指针的基本用法

1. 定义指针

在Go语言中,使用*操作符定义指针变量。例如:

package mainimport "fmt"func main() {var x int = 42var p *int = &x // 定义一个int类型的指针变量p,并将x的地址赋值给p//获取指针指向的地址中存的值fmt.Println(*p)
}

在这里插入图片描述

2. 使用new函数创建指针

new函数用于创建一个指定类型的零值指针变量。例如:

p := new(int) // 创建一个int类型的零值指针变量
*p = 42 // 通过指针设置值
fmt.Println("Value stored in p:", *p)

在这里插入图片描述

3. 指针作为函数参数

将指针作为函数参数,可以在函数内部修改原始变量的值,从而避免函数对变量进行拷贝,提高程序的性能。例如:

func changeValue(a *int) {*a = 20
}func main() {x := 10fmt.Println("Before:", x)changeValue(&x)fmt.Println("After:", x)
}

输出结果为:

Before: 10
After: 20

这表明我们通过指针修改了x的值。

4. 指针作为函数返回值

函数可以返回指针类型的值,以便在函数外部访问函数内部创建的变量。

package mainimport "fmt"// 指针函数, 指针是可以用作函数的返回值
func main() {// 调用了这个函数后,可以得到一个指针类型的变量。ptr := f5()//内存地址正常打印前面带个&fmt.Println("ptr:", ptr)fmt.Printf("ptr:%p\n", ptr)fmt.Printf("ptr类型:%T\n", ptr)fmt.Println("ptr的地址:", &ptr)fmt.Println("ptr地址中的值:", *ptr)// 使用fmt.Println((*ptr)[0])ptr[0] = 10fmt.Println(ptr[0])}// 调用该函数后返回一个指针,此时返回个数组指针
func f5() *[4]int {arr := [4]int{1, 2, 3, 4}//内存地址往往被赋值给指针return &arr}

在这里插入图片描述

5. 空指针检查

在使用指针之前,应该进行空指针检查,以避免出现空指针引用的错误。可以使用nil值来表示空指针。例如:

package mainimport "fmt"func main() {var p *int // 声明一个int类型的指针变量,默认值为nilif p != nil {fmt.Println(*p) // 对非空指针进行操作} else {fmt.Println("Pointer is nil")}
}

在这里插入图片描述

三、指针的高级用法

1. 指针数组和指针切片

指针数组和指针切片允许我们存储多个指针变量,并通过这些指针访问和修改对应的值。

指针数组
package mainimport "fmt"func main() {a := 1b := 2c := 3d := 4// 创建一个指针数组arr1 := [4]*int{&a, &b, &c, &d}fmt.Println(arr1)// 通过指针修改a的值// arr1[0] 0xc00000e0a8*arr1[0] = 100fmt.Println(a)a = 200fmt.Println(*arr1[0])
}

在这里插入图片描述

指针切片
slice := []int{4, 5, 6}
var pSlice *[]int = &slice
fmt.Println("Pointer to Slice:", *pSlice)

2. 数组指针

数组指针,首先应该是一个指针,指向了一个数组

package mainimport "fmt"// 数组指针
func main() {// 创建数组,值传递。funarr1 := [4]int{1, 2, 3, 4}fmt.Println("arr1:", arr1)fmt.Printf("arr1指向的地址:%p\n", &arr1)// 创建一个指针,指向这个数组的地址,通过指针来操作数组//var p1 *[4]int//创建指针方法二p1 := new([4]int)p1 = &arr1fmt.Printf("p1指向的地址: %p\n", p1)fmt.Printf("p1自己的地址: %p\n", &p1)fmt.Println("p1指向的地址的值: ", *p1)fmt.Printf("p1指向的地址的值: %v\n", *p1)// 操作数组指针 来修改数组(*p1)[0] = 100 // 原生写法fmt.Println("arr1:", arr1)fmt.Println("p1指向的地址的值: ", *p1)// 语法糖:由于p1指向了arr1这个数组,所以可以直接用p1来操控数组// 指向了谁,这个指针就可以代表谁。// p1 = arr1p1[0] = 200 // 在程序中,我们更多时候是这样在使用指针的fmt.Println("arr1:", arr1)fmt.Println("p1指向的地址的值: ", *p1)}

在这里插入图片描述

3. 指针和切片

在Go语言中,切片本身就是通过指针引用的,因此修改切片元素的值也会影响到原始数组。但是,当重新分配切片时(例如使用append函数),切片的底层数组可能会改变,此时原有的切片指针将不再指向新的底层数组。

func modifySlice(s *[]int) {(*s)[0] = 99*s = append(*s, 100)
}func main() {slice := []int{1, 2, 3}fmt.Println("Original Slice:", slice)modifySlice(&slice)fmt.Println("Modified Slice:", slice)
}

4. 指针和方法

在Go语言中,方法的接收者可以是值类型或指针类型。使用指针作为接收者可以减少数据拷贝,提高性能,特别是当处理大型结构体时。

type Rectangle struct {Width  intHeight int
}func (r *Rectangle) Area() int {return r.Width * r.Height
}func main() {rect := Rectangle{Width: 5, Height: 10}fmt.Println("Area:", rect.Area())
}

5. 接口中的指针

在Go语言中,接口是一种类型,它定义了对象的行为。当接口的实现是大型结构体时,使用指针作为接口的实现可以减少数据拷贝,提高性能。

type Shape interface {Area() float64
}type Circle struct {Radius float64
}func (c *Circle) Area() float64 {return math.Pi * c.Radius * c.Radius
}func printArea(s Shape) {fmt.Println("Area:", s.Area())
}func main() {circle := Circle{Radius: 5}printArea(&circle) // 注意这里传递的是&circle,因为Circle的Area方法接收的是指针
}

注意:在上面的printArea函数调用中,我们传递了&circle而不是circle,因为CircleArea方法接收的是*Circle类型的参数。

6. 指针的指针

指针的套娃,指针指向指针 , 指针类型 第一个*指针类型, *int是这个指针对应的类型。
如何理解多个符号,第一个取出来后,后面就是它存的类型 *(*(int))

package mainimport "fmt"func main() {// 声明 普通变量var a int = 10// 声明 指针变量,指向a, 指针其实就是一个特殊的变量而已。,ptr命名  p// 定义变量格式  var ptr *类型var p *intp = &a // 指针变量赋值// 指针的套娃,指针指向指针 , 指针类型 第一个*指针类型, *int是这个指针对应的类型// 如何理解多个符号,第一个取出来后,后面就是它存的类型 *(*(int))var ptr **intptr = &p//fmt.Printf("ptr变量存储的指针的地址:%p\n", ptr) //就是p的地址fmt.Printf("ptr变量自己的地址:%p\n", &ptr)fmt.Printf("*ptr变量存储的地址:%p\n", *ptr)     //就是p存的指针的地址fmt.Printf("*ptr变量存储的地址中的值:%d\n", **ptr) //就是p存的指针的地址指向的值,即是a的值// 修改变量a就有了无数种方式**ptr = 1111fmt.Println(a)
}

在这里插入图片描述

四、总结

指针在Go语言中是一种非常强大的工具,它允许我们直接访问和修改内存中的值,优化内存使用和提高程序性能。然而,过度使用指针也可能导致代码难以理解和维护,还可能引发内存泄漏和悬空指针等问题。因此,在使用指针时要谨慎,并遵循Go语言的指针使用规范。

通过本文的详细讲解和具体案例,相信读者已经对Go语言中的指针有了更深入的了解。在实际开发中,可以根据项目需求,在合适的场景中使用指针来优化程序性能。

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

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

相关文章

《操作系统 - 清华大学》1 -1:操作系统概述 —— 内容概述

文章目录 1. 内容摘要2. 实验内容 1. 内容摘要 在这里对学习内容做一个整体上的介绍,那在这里包括我们要学习的内容,实验的内容。操作系统课涉及到计算机系统当中的资源管理,所以我们围绕着操作系统的实现来介绍相关内容,那主要分…

优化 Go 语言数据打包:性能基准测试与分析

场景:在局域网内,需要将多个机器网卡上抓到的数据包同步到一个机器上。 原有方案:tcpdump -w 写入文件,然后定时调用 rsync 进行同步。 改造方案:使用 Go 重写这个抓包逻辑及同步逻辑,直接将抓到的包通过网…

大势智慧亮相“第十届博博会”,展现数字文旅新质生产力!

2024年8月23日至26日,由国家文物局指导,中国博物馆协会主办的第十届“中国博物馆及相关产品与技术博览会”(简称“博博会”)在呼和浩特敕勒川国际会展中心成功举办。 呼和浩特敕勒川国际会展中心 大势智慧携数字文旅全栈解决方案以…

SpringBoot框架下的客户管理策略

1 绪论 1.1研究背景 随着网络不断的普及发展,企业客户管理系统依靠网络技术的支持得到了快速的发展,首先要从员工的实际需求出发,通过了解员工的需求开发出具有针对性的首页、个人中心、员工管理、客户信息管理、行业类型管理、项目信息管理、…

新能源汽车充电桩怎么选?

新能源汽车是我国七大战略性新兴产业之一,已成为汽车产业转型升级的重要推动力。毫无疑问。充电桩作为我国新能源汽车产业链下游的重要环节,在国家政策的大力支持和市场需求的带动下,有着非常广阔的前景。安科瑞叶西平187-06160015 新能源汽…

数据结构---顺序表之单链表

1.链表的概念 链表是一种逻辑上是线性的,但物理结构不一定是线性的数据结构,它通过链表中的指针链接次序实现的 链表的存储空间是我们通过动态内存开辟的内存空间,所以他们的地址可能是连续的也可能不是连续的 2.链表的分类 1.单向或者双向…

Footprint Analytics: 我们为何打造 Growthly 这款产品

在 Web3 的领域内,数据已成为新的“财富”。在 Footprint Analytics,我们始终站在区块链数据分析的最前沿,提供全方位的解决方案,为 Web3 生态中的企业和项目简化数据分析的复杂性。然而,随着我们对客户需求及行业趋势…

VLAN原理与接口

在学习之前,先抛出问题:什么是VLAN?VLAN工作原理是什么?VLAN如何配置? VLAN的定义 VLAN(Virtual Local Area Network,虚拟局域网)是一种在逻辑上将局域网设备从物理上划分的网络技…

一种单目标A*算法设计与实现

一种单目标A*算法设计与实现 作者:吴屏珊 最近在学习简单的单目标A*算法,其中在CSDN上阅读到的一篇博文给了我很大启发,于是在该博文的基础上,笔者记录了一点自己对于A*算法的体会和感悟。原文链接 目录 文章目录 一种单目标A*…

微信接口报错:Http头Authorization中的timestamp与 发起请求的时间不得超过5分钟

在发起请求的时候微信会自己封装一个系统时间 当服务器系统时间与实际实际相差5分钟或者5分钟以上就会出现这个错误 需要修改系统时间 问一下ChatGPT 用自动同步 sudo timedatectl set-ntp true 服务器执行 , 过个一分钟 再查看时间 发现正确 再支付就可以成功…

Spring6梳理11——依赖注入之注入List集合类型属性

以上笔记来源: 尚硅谷Spring零基础入门到进阶,一套搞定spring6全套视频教程(源码级讲解)https://www.bilibili.com/video/BV1kR4y1b7Qc 11 依赖注入之注入List集合类型属性 11.1 创建实体类Emp以及Dept Dept类中添加了遍历Emp…

Java语法-类和对象(上)

1. 面向对象的初步认识 1.1 什么是面向对象 概念: Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象。 1.2 面向对象VS面向过程 如:洗衣服 面向过程: 注重的是洗衣服的过程,少了一个环节也不…

七层负载均衡和四层负载均衡的区别

文章目录 什么是七层负载均衡?一、定义与工作原理二、优点与缺点三、应用场景四、常见七层负载均衡器五、负载均衡算法 什么是四层负载均衡?一、定义与原理定义:原理: 二、特点与应用场景特点:应用场景: 三…

python类的call方法与init方法

1. call方法 在对象被调用了的时候就会调用call方法a(666) class A:def __call__(self, args):print(call 方法被调用了,args) aA() a(666) 2.init方法 创建对象的时候 init 方法被调用 class A:def __init__(self,args):print(创建对象的时候 init 方法被调用了,args) aA(…

三、LLM应用开发准备工作

LLM应用开发准备工作 开发基础开发工具大模型kx上网key的配置与使用网站结语 开发基础 最好具备一定的Python开发基础,不需要特别深 如果不具备,可以先学习一下基础知识(概念),比如Python环境管理、包管理与使用、基本…

城市酷选:如何四年做到3000亿销售额 会员超500w

城市酷选,这一融合了线上线下消费的会员制社交电商平台,正以其独特的运营模式在市场中崭露头角。该平台不仅汇聚了超过600万的会员与60万商家,更实现了年交易额的百亿突破,彰显了其强大的市场影响力和消费者吸引力。 创新排队免单…

必应bing推广kai户流程教学,满足企业获客需求

微软Bing广告提供了三种主要广告类型,可以满足大多数出海企业的展示和客户获取需求。 搜索广告(Search Ads) 包括标准搜索广告和动态搜索广告。当用户的搜索词与投放的关键词匹配时,相应的搜索广告会被触发,向用户展示…

基于深度学习的数字识别系统的设计与实现(python、yolov、PyQt5)

💗博主介绍💗:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示:文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

Nginx 的优化与防盗链设置

Nginx的优化 隐藏版本号 暴露版本号,攻击者就可以根据版本漏洞进行攻击。 查看版本号的方法: curl -I http://192.168.110.60 网页访问F12查看源代码 隐藏版本号的方法 方法一、修改配置文件 添加关闭版本号 vim /usr/local/nginx/conf/nginx.conf…

构建高效企业客户管理系统:SpringBoot应用

1 绪论 1.1研究背景 随着网络不断的普及发展,企业客户管理系统依靠网络技术的支持得到了快速的发展,首先要从员工的实际需求出发,通过了解员工的需求开发出具有针对性的首页、个人中心、员工管理、客户信息管理、行业类型管理、项目信息管理、…