当前位置: 首页 > 科技观察

读到这里,我彻底理解了Golang的指针

时间:2023-03-21 20:36:37 科技观察

golang中一个非常有特色的地方就是引入了指针的使用。这个在py、php、java中是不支持的,但是很多读者反映,指针我不太了解,所以今天写了这篇文章。当然,我尽量使用通俗易懂的语言。我希望它对你有用。什么是指针想知道什么是指针,首先要明白数据是如何获取的funcmain(){varainta=1fmt.Println("a的值",a)}以上代码很简单,相信不懂golang的读者应该也能看懂。但是他到底在做什么?你真的了解了吗?接下来我们一一解释下varaint。第一步是在内存中为变量a开辟一块空间。因为是int类型,所以空间大小是4个字节。那么问题来了,“这个空间是在Whereisthememorylocation打开的?”首先,这个位置是系统“随机分配”的一块。另外给这块内存做一个“标记”,方便下次查找,“这个标记在这块内存的开头”a=1然后给变量a赋值1.那么系统是如何分配的呢?首先你要找到a的内存在哪里?“如何找到分配给a的那块内存?”当然是通过之前对a变量所做的“标记”。通过标记找到这块内存的位置,然后直接把赋值给a的数据存到开辟的内存空间中。对于代码fmt.Println("a的值",a),我们暂时不需要了解fmt.Println是如何实现的,我们只需要关心a是如何获取的,当然首先“在做之前找到一个”的标记,找到对应内存的位置,向后偏移4个位置,取出值即可。现在感觉清楚了吗?在上面的过程中,我们提到的“标记”就是“指针”。所以指针其实是一种“标记数据所在位置的数据类型”,只是它有自己的一些特殊语法,是一种新的数据类型。从这个角度来看,很简单。指针的定义指针是一种“数据类型”,用来表示数据的“内存地址”。指针的使用方法看下面的例子感受一下case1varastring//声明一个string类型的变量,初值为""varb*string//声明一个string指针类型的变量,初值为nil,声明指针类fmt.Println("a:",a,"b:",b)//输出结果为//a:b:注意:声明指针的类型,只需要在前面加一个*就可以了,这是一个固定的语法不管什么指针类型(*int,*string,*float),初始值都是nilcase2varnamestring="Xiaofan"//声明一个name为string类型,andassignthevalueto"smallFan"varp_name*string=&name//声明一个p_name为*string(字符串指针类型),赋值给&a(在a前面加一个&表示取a的首地址)fmt.Println("name:",name,"name的内存地址",&name,"p_name:",p_name,"p_name的具体值:",*p_name)//输出结果为//name:the小凡名字的内存地址0x14000010240p_name:0x14000010240p_name的具体取值:注意变量名的首地址,也就是指针的值,需要用&name来表示,提取出来的值只能用指针的变量类型来保存,所以varp_name*string=&name这段代码是合理的。p_name的具体值是一个随机分配的十六进制值,0x14000010240。只知道这代表了指针的值。因为是随机分配的,所以不同的设备是不一样的。获取指针类型指向的具体值,直接使用*(对应指针类型的变量名)即可获取。比如上面的例子,“对应的指针类型的变量名为p_name,所以可以直接使用*p_name获取指针p_name指向的具体值”。说明上面我们通过&name获取到name的内存空间地址是0x14000010240,变量p_name的值其实就是name变量的内存空间的值,而p_name也是一个变量,那么value所在的地方p_name变量的存储,是不是也有一块内存空间呢?是的,指针变量p_name也会指向一块内存空间address:",&p_name)//output//name:小凡的p_name的值为0x14000010240p_name指针变量的内存地址:0x1400000e028指针在数组中的应用首先要区分一个概念,“数组指针”和“指针数组”“不同之处。数组指针简单来说就是整个数组是一个指针,b,c:=1,2,3arr:=[3]int{a,b,c}varptrArr*[3]intptrArr=&arrarr[1]=200//改变数组的值不会影响变量本身fmt.Println(b)fmt.Println(arr[1])fmt.Println((*ptrArr)[1])//可以简单写成as:ptrArr[1]//结果输出为//2//200//200直接改变数组的一个元素,不影响对应元素的变量。指针数组简单的说就是数组的每个元素都是一个指针,b,c:=1,2,3arr:=[3]int{a,b,c}arr[1]=2//修改法线arrayValue//定义指针数组varptrArr[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当然是指针数组和数组指针有很多细节需要注意。如果这篇文章的阅读量还不错,后面我们会专门写一篇文章来说明这个问题。这里做一个简单的理解。希望大家记得转发,多多点赞。指针在函数中的应用case1funcmain(){varaint=123changeData(a)fmt.Println(a)}funcchangeData(bint){b=456}//outputresult//123想象一下最终打印的a出来的是123还是456,当然是123了,为什么会这样呢?因为碰到changeData,把a传进去之后,相当于执行了一个步骤varbintb=1,所以自然对b的任何修改都不会影响到a,输出自然是123case2funcmain(){varaint=123changeData(&a)fmt.Println(a)}funcchangeData(b*int){*b=456}在这个函数传参中,相当于执行varb*intb=&ab是指向a的指针,所以*如果b修改了,a自然也要相应修改。golang指针和c语言指针的区别。我们都知道C语言之所以强大,是因为C语言支持指针,权限非常大。C语言可以对计算机中任意内存的指针进行操作,这自然会带来一些不安全感。因素,所以在golang中,“取消了一些指针偏移、翻转等算术运算”(+、-、++、--)所以使用起来更安全。