文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

看完这个,我彻底理解了Golang的指针

2024-12-01 13:38

关注

什么是指针

想了解什么是指针,你先得了解数据是怎么取到的

func main() {
var a int
a = 1
fmt.Println("a的值为", a)
}

上述代码非常简单,我相信不会golang的读者应该也能看懂。但是他底层究竟干嘛了?你真的了解过么?接下来咱们逐一解释

var a int

首先这一步,是给变量a,在内存中开辟了一块空间,因为是int类型,所以空间大小为4个字节,那么问题来了,「这块空间开在内存哪个位置?」 首先这块位置是系统「随机分配」的一块。另外给这块内存做了一个「标记」,方便下次找到,「这个标记就在这块内存的起始的位置」

a = 1

接下来给变量a赋值为1。那么系统如何赋值的呢?首先总得找到a这块内存在哪吧?「如何找到给a分配的那块内存的呢?」当然是通过之前给a变量做的那个「标记」。通过标记找到这块内存所在的位置,然后直接在开辟好的内存空间存下给a赋值的数据就可以了。

fmt.Println("a的值为", a)

这段代码,我们暂且先不用去了解fmt.Println是怎么实现的,只用关心a是怎么取到的,当然是先「找到a之前所做的那个标记」,找到对应的内存所在的位置,直接往后偏移4个位置把值取出来就行。

这下是不是感觉清晰明了了?

我们在上述过程中,所说的「标记」,就是「指针」.所以指针其实就是一个「标记数据所在位置的数据类型而已」,只不过他有一些自己特殊的语法而已,而且是一种新的数据类型。这么来看,就很简单了。

指针的定义

指针是一种「数据类型」,用于表示数据的「内存地址」。

如何使用指针

我们来看下面几个例子感受一下

case1

var a string  //声明一个字符串类型的变量,初始值为""
var b *string //声明一个字符串指针类型的变量,初始值为nil,声明指针类
fmt.Println("a:", a, " b:", b)
//输出结果为
//a: b: <nil>

注意:

case2

var name string = "小饭"   //声明一个name为string类型,并且赋值为"小饭"
var p_name *string = &name //声明一个p_name为*string(字符串的指针类型),并且赋值为&a(在a前面加上一个&的意思是取a的首地址)
fmt.Println("name:", name, "name的内存地址", &name, " p_name:", p_name, "p_name的具体值:", *p_name)
//输出结果为
//name: 小饭 name的内存地址 0x14000010240 p_name: 0x14000010240 p_name的具体值:

注意

说明

上面我们通过&name获取到了name的内存空间的地址是0x14000010240,p_name的变量的值实际上是name变量的内存空间的值,p_name也是一个变量 那么p_name变量所存放值的地方,是不是也会有一个内存空间呢?是的,p_name这个指针变量也会指向一个内存空间

var name string = "小饭"
var p_name *string = &name

fmt.Println("name:", name, "p_name的值", p_name, " p_name指针变量的内存地址:", &p_name)
//输出
//name: 小饭 p_name的值 0x14000010240 p_name指针变量的内存地址: 0x1400000e028

指针在数组中的应用

大家首先得区分一个概念,「数组指针」和「指针数组」的区别。

数组指针

简单说数组指针就是整个数组都为指针

, b, c := 1, 2, 3
arr := [3]int{a, b, c}
var ptrArr *[3]int
ptrArr = &arr
arr[1] = 200 //改变数组的值,并不会影响到对应数组元素的变量本身
fmt.Println(b)
fmt.Println(arr[1])
fmt.Println((*ptrArr)[1]) // 可以简单写为:ptrArr[1]
//结果输出为
//2
//200
//200

直接改变数组的某个元素,不会影响到对应元素的变量。

指针数组

简单说就是数组每个元素都为指针

, b, c := 1, 2, 3
arr := [3]int{a, b, c}
arr[1] = 2 // 修改普通数组中的值
// 定义指针数组
var ptrArr [3]*int //每个元素为一个指针
ptrArr = [3]*int{&a, &b, &c}
*ptrArr[1] = 200 //修改某个元素的指,不会影响到数组本身
fmt.Println(b)
fmt.Println(arr[1])
fmt.Println(*ptrArr[1])
//结果输出
//200
//2
//200

当然指针数组和数组指针有很多细节需要注意,如果这篇文章阅读量还可以,咱们后面专门会开一篇讲解这个问题。在这里有个简单的认识即可。希望大家记得多多转发和点赞哦。

指针在函数中的应用

case1

func main() {
var a int = 123
changeData(a)
fmt.Println(a)
}
func changeData(b int) {
b = 456
}
//输出结果
//123

大家想象一下最终打印出来的a是123 还是456,当然是123.为什么会这样呢?因为运行到changeData中,把a传进去之后,相当于执行了一步

var b int
b = 1

所以自然对b进行任何修改都不会影响到a,输出的自然是123

case2

func main() {
var a int = 123
changeData(&a)
fmt.Println(a)
}
func changeData(b *int) {
*b = 456
}

在这一次函数参数传递中,相当于执行了

var b *int
b = &a

b就是指向a的指针,所以*b修改了,a自然也会跟着修改。

golang指针和c语言指针的区别

大家知道C语言之所以强大,就是因为c语言支持指针,而且权限特别大,c语言可以对计算机中任何内存的指针进行操作,这样自然而然也会带来一些不安全的因素,所以在golang中,「取消了对指针的一些偏移,翻转等算术运算」(+、-、++、--)所以使用起来更安全。

来源:程序员小饭内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯