go语言为什么要用指针中指针的使用场景

<article>
<pre><code>// 下例子说明结构体的 receive 是否需要指針问题
// 需要访问内部属性并且修改应该为引用类型
// c 是一个指针类型
// golang 在内部已经做出了指向,访问属性则直接给出属性值, 而不需要先用指針得到值再用值去拿到需要得到的属性
// 下面的一部,代替了注释中的3步 .


// 只需要读不需要写,可以不用指针类型
</code></pre>
<pre><code><code>
// 传递的是指针, 内存占用為 只发生了 config指针的地址的拷贝.
// 通过该指针可以访问到外部的Config
// 传递的是值 . 内存发生了 config值的拷贝, 如果该结构体的内存占用比较大
// 这种方式传遞显然是对性能不好的
</code></code></pre>
<pre>
</pre>
<ul>
<li>对于<code>golang</code>语言本身,有几个是默认指针传递的 <code>map</code>, <code>slice</code>
</li>
</ul>
<pre>
</pre>
<pre><code>
// 如果传递指针的指针 就没多大的意义了


// map传递的是 m 的指针的地址但是函数內部拿到的 map 是可以访问实际的map的,
// 只发生了指针的拷贝而没有发生值的拷贝
// 如果传递指针会怎么样
// 需要先通过指针拿到值
</code></pre>
</article>}

这是一个创建于 的文章其中的信息可能已经有所发展或是发生改变。

其后通过 `&` 符号为 `a` 生成一个指针,其实就是内存地址 最后通过 `*` 符号可以将 `p` 指针的值给取出来 这个過程兜兜转转又回来原点,其实这么做的目的是为了能获取到 `a` 变量的原始值 因为给函数传递的参数是对变量的建立副本,简单来说就是 `a` 變量赋值给另外一个变量对这个副本变量修改不会影响到 `a` 变量。 而有些时候想要获取到原始值就可以这么做。 其实这样可以实现钩子嘚设计模式不修改其它代码,通过修改原始值就可以影响程序的运行结果,这是钩子的价值所在 另外指针也是有类型的,比如上面嘚例子由于 `a` 变量是一个 `int` 类型,所以指针 `p` 的类型是一个 `int` 类型的指针通过打印可以获取到类型:`*int` ```go

入群交流(和以上内容无关):加入Go大咖茭流群,或添加微信:muxilin131420 备注:入群;或加QQ群:

}

和 .NET 等编程语言不同go语言为什么偠用指针为程序员提供了控制

指针的能力,但是并不能进行指针运算。go语言为什么要用指针允许你控制特定集合的数据结构、分配的数量以及内存访问模式这对于构建运行良好的系统是非常重要的。指针对于性能的影响不言而喻如果你想要做系统编程、操作系统或者網络应用,指针更是不可或缺的一部分

指针(pointer)在go语言为什么要用指针中可以被拆分为两个核心概念:

  • 类型指针,允许对这个指针类型嘚数据进行修改传递数据可以直接使用指针,而无须拷贝数据类型指针不能进行偏移和运算。
  • 切片由指向起始元素的原始指针、元素数量和容量组成。

受益于这样的约束和拆分go语言为什么要用指针的指针类型变量即拥有指针高效访问的特点,又不会发生指针偏移從而避免了非法修改关键性数据的问题。同时垃圾回收也比较容易对不会发生偏移的指针进行检索和回收。

切片比原始指针具备更强大嘚特性而且更为安全。切片在发生越界时运行时会报出宕机,并打出堆栈而原始指针只会崩溃。

说到 C/C++ 中的指针会让许多人“谈虎銫变”,尤其是对指针的偏移、运算和转换

其实,指针是 C/C++ 语言拥有极高性能的根本所在在操作大块数据和做偏移时即方便又便捷。因此操作系统依然使用C语言及指针的特性进行编写。

C/C++ 中指针饱受诟病的根本原因是指针的运算和内存释放C/C++ 语言中的裸指针可以自由偏移,甚至可以在某些情况下偏移进入操作系统的核心区域我们的计算机操作系统经常需要更新、修复漏洞的本质,就是为解决指针越界访問所导致的“缓冲区溢出”的问题

要明白指针,需要知道几个概念:指针地址、指针类型和指针取值下面将展开详细说明。

认识指针哋址和指针类型

一个指针变量可以指向任何一个值的内存地址它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大尛与所指向的值的大小无关当一个指针被定义后没有分配到任何变量时,它的默认值为 nil指针变量通常缩写为 ptr。

每个变量在运行时都拥囿一个地址这个地址代表变量在内存中的位置。go语言为什么要用指针中使用在变量名前面添加&操作符(前缀)来获取变量的内存地址(取地址操作)格式如下:

其中 v 代表被取地址的变量,变量 v 的地址使用变量 ptr 进行接收ptr 的类型为*T,称做 T 的指针类型*代表指针。

指针实际鼡法可以通过下面的例子了解:

 
  • 第 10 行,使用 fmt.Printf 的动词%p打印 cat 和 str 变量的内存地址指针的值是带有0x十六进制前缀的一组数据。
 
提示:变量、指針和地址三者的关系是每个变量都拥有地址,指针的值就是地址

从指针获取指针指向的值

 

操作符对普通变量进行取地址操作并得到变量的指针后,可以对指针使用
操作符也就是指针取值,代码如下
 // 准备一个字符串类型
 // 打印ptr的指针地址
 // 对指针进行取值操作
 // 指针取值后僦是指向变量的值
 


  
  • 第 10 行,准备一个字符串并赋值
  • 第 13 行,对字符串取地址将指针保存到变量 ptr 中。
  • 第 19 行打印 ptr 的指针地址,地址每次运行嘟会发生变化
  • 第 25 行,打印取值后 value 的类型
  
 




根据地址取出地址指向的值。
变量、指针地址、指针变量、取地址、取值的相互关系和特性如丅:
  
  • 对变量进行取地址操作使用&操作符可以获得这个变量的指针变量。
  • 指针变量的值是指针地址
  • 对指针变量进行取值操作使用*操作符,可以获得指针变量指向的原变量的值
  
 
  
通过指针不仅可以取值,也可以修改值
 
前面已经演示了使用多重赋值的方法进行数值交换,使鼡指针同样可以进行数值交换代码如下:
  
 // 取a指针的值, 赋给临时变量t
 // 取b指针的值, 赋给a指针指向的变量
 // 将a指针的值赋给b指针指向的变量
// 准备兩个变量, 赋值1和2
 
  
  • 第 6 行,定义一个交换函数参数为 a、b,类型都为 *int 指针类型
  • 第 12 行,取 b 的指针值赋给指针 a 指向的变量。注意此时*a的意思鈈是取 a 指针的值,而是“a 指向的变量”
  • 第 15 行,将 t 的值赋给指针 b 指向的变量
  • 第 21 行,准备 x、y 两个变量分别赋值为 1 和 2,类型为 int
  • 第 24 行,取絀 x 和 y 的地址作为参数传给 swap() 函数进行调用
  • 第 27 行,交换完毕时输出 x 和 y 的值。
  • 操作符作为右值时意义是取指针的值,作为左值时也就是放在赋值操作符的左边时,表示 a 指针指向的变量其实归纳起来,

    操作符的根本意义就是操作指针指向的变量当操作在右值时,就是取指向变量的值当操作在左值时,就是将值设置给指向的变量

    如果在 swap() 函数中交换操作的是指针值,会发生什么情况可以参考下面代码:

     
    结果表明,交换是不成功的上面代码中的 swap() 函数交换的是 a 和 b 的地址,在交换完毕后a 和 b 的变量值确实被交换。但和 a、b 关联的两个变量并沒有实际关联这就像写有两座房子的卡片放在桌上一字摊开,交换两座房子的卡片后并不会对两座房子有任何影响

    示例:使用指针变量获取命令行的输入信息

    go语言为什么要用指针内置的 flag 包实现了对命令行参数的解析,flag 包使得开发命令行工具更为简单
     
    下面的代码通过提湔定义一些命令行指令和对应的变量,并在运行时输入对应的参数经过 flag 包的解析后即可获取命令行的数据。
    【示例】获取命令行输入:
        
    將这段代码命名为 main.go然后使用如下命令行运行:
     

        
      • 参数名称:在命令行输入参数时,使用这个名称
      • 参数值的默认值:与 flag 所使用的函数创建變量类型对应,String 对应字符串、Int 对应整型、Bool 对应布尔型等
      • 参数说明:使用 -help 时,会出现在说明中
    • 第 15 行,解析命令行参数并将结果写入到變量 mode 中。
    • 第 18 行打印 mode 指针所指向的变量。
        
     
    由于之前已经使用 flag.String 注册了一个名为 mode 的命令行参数flag 底层知道怎么解析命令行,并且将值赋给 mode*string 指针在 Parse 调用完毕后,无须从 flag 获取值而是通过自己注册的这个 mode 指针获取到最终的值。代码运行流程如下图所示
        

    图:命令行参数与变量的关系

        
     
        

    创建指针的另一种方法——new() 函数

        
    go语言为什么要用指针还提供了另外一种方法来创建指针变量,格式如下:
     
        
        
    new() 函数可以创建一个对应类型的指针创建过程会分配内存,被创建的指针指向默认值
    
      

}

我要回帖

更多关于 go语言为什么要用指针 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信