go语言有指针运算吗
来源:亿速云
时间:2023-03-09 14:26:10 421浏览 收藏
从现在开始,我们要努力学习啦!今天我给大家带来《go语言有指针运算吗》,感兴趣的朋友请继续看下去吧!下文中的内容我们主要会涉及到go语言等等知识点,如果在阅读本文过程中有遇到不清楚的地方,欢迎留言呀!我们一起讨论,一起学习!
本篇内容介绍了“go语言有指针运算吗”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
go语言没有指针运算。go语言的语法上是不支持指针运算的,所有指针都在可控的一个范围内使用;但实际上,go语言可以通过unsafe包的Pointer()方法把指针转换为uintptr类型的数字,来间接实现指针运算。
内存就是一系列有序列号的存储单元,变量就是编译器为内存地址分配的昵称,那么指针是什么呢?
指针就是一个指向另一个内存地址变量的值
指针指向变量的内存地址,指针就像该变量值的内存地址一样
我们来看一个代码片段
func main() { a := 200 b := &a *b++ fmt.Println(a) }
在 main 函数的第一行,我们定义了一个新的变量 a ,并赋值为 200。接下来我们定义了一个变量 b ,并将变量 a 的地址赋值给 b 。我们并不知道 a 的准确存储地址,但是我们依然可以将 a 的地址存储在变量 b 中。
因为 Go 强类型的特性,第三行代码也许是最具干扰性的了,b 包含 a 变量的地址,但是我们想增加存储在 a 变量中的值。
这样我们必须取消引用 b ,而是跟随指针由 b 引用 a。
然后我们将该值加 1 后,存储回 b 中存储的内存地址上。
最后一行打印了 a 的值,可以看到 a 的值已经增加为了 201
Go语言中的函数传参都是值拷贝,当我们想要修改某个变量的时候,我们可以创建一个指向该变量地址的指针变量。
区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。
要搞明白Go语言中的指针需要先知道3个概念:指针地址、指针类型和指针取值。
指针地址和指针类型
Go语言中的指针操作非常简单,只需要记住两个符号:&(取地址)和*(根据地址取值)。
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用&字符放在变量前面对变量进行“取地址”操作。
取变量指针的语法如下:
ptr := &v // v的类型为T
其中:
v:代表被取地址的变量,类型为T
ptr:用于接收地址的变量,ptr的类型就为*T,称做T的指针类型。*代表指针。
func main() { a := 10 b := &a fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078 fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int fmt.Println(&b) // 0xc00000e018 }
指针运算符
1.指针运算符为左值时,我们可以更新目标对象的状态;而为右值时则是为了获取目标的状态。
func main() { x := 10 var p *int = &x //获取地址,保存到指针变量 *p += 20 //用指针间接引用,并更新对象 println(p, *p) //输出指针所存储的地址,以及目标对象 }
输出:
0xc000040780 30
2.指针类型支持相等运算符,但不能做加减运算和类型转换。如果两个指针指向同一地址,或都为nil,那么它们相等。
func main() { x := 10 p := &x p++ //编译报错 invalid operation: p++ (non-numeric type *int) var p2 *int = p+1 //invalid operation: p + 1 (mismatched types *int and int) p2 = &x println(p == p2) //指向同一地址 }
可通过unsafe.Pointer将指针转换为uintptr后进行加减法运算,但可能会造成非法访问。
指针运算
在很多 golang 程序中,虽然用到了指针,但是并不会对指针进行加减运算,这和 C 程序是很不一样的。Golang 的官方入门学习工具(go tour) 甚至说 Go 不支持指针算术。虽然实际上并不是这样的,但我在一般的 go 程序中,好像确实没见过指针运算(嗯,我知道你想写不一般的程序)。
但实际上,go 可以通过
unsafe.Pointer
来把指针转换为uintptr
类型的数字,来间接实现指针运算。这里请注意,
uintptr
是一种整数类型,而不是指针类型。
比如:
uintptr(unsafe.Pointer(&p)) + 1
就得到了 &p
的下一个字节的位置。然而,根据 《Go Programming Language》 的提示,我们最好直接把这个计算得到的内存地址转换为指针类型:
unsafe.Pointer(uintptr(unsafe.Pointer(&p) + 1))
因为 go 中是有垃圾回收机制的,如果某种 GC 挪动了目标值的内存地址,以整型来存储的指针数值,就成了无效的值。
同时也要注意,go 中对指针的 + 1,真的就只是指向了下一个字节,而 C 中 + 1
或者 ++
考虑了数据类型的长度,会自动指向当前值结尾后的下一个字节(或者说,有可能就是下一个值的开始)。如果 go 中要想实现同样的效果,可以使用 unsafe.Sizeof
方法:
unsafe.Pointer(uintptr(unsafe.Pointer(&p) + unsafe.Sizeof(p)))
最后,另外一种常用的指针操作是转换指针类型。这也可以利用 unsafe 包来实现:
var a int64 = 1 (*int8)(unsafe.Pointer(&a))
如果你没有遇到过需要转换指针类型的需求,可以看看这个项目(端口扫描工具),其中构建 IP 协议首部的代码,就用到了指针类型转换。
“go语言有指针运算吗”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注golang学习网,小编将为大家输出更多高质量的实用文章!
好了,本文到此结束,带大家了解了《go语言有指针运算吗》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多Golang知识!
-
185 收藏
-
460 收藏
-
430 收藏
-
450 收藏
-
320 收藏
-
199 收藏
-
145 收藏
-
168 收藏
-
165 收藏
-
473 收藏
-
377 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习