为了账号安全,请及时绑定邮箱和手机立即绑定

在Go中使用指针有什么意义?

在Go中使用指针有什么意义?

Go
慕姐4208626 2021-04-08 18:15:56
我知道Go中的指针允许函数参数的突变,但是如果它们仅采用引用(带有适当的const或可变限定符),会不会更简单。现在,我们有了指针,并且对于某些内置类型(例如,映射和通道)进行隐式按引用传递。我是否缺少某些东西,或者Go中的指针仅仅是不必要的复杂性?
查看完整描述

3 回答

?
斯蒂芬大帝

TA贡献1827条经验 获得超8个赞

指针之所以有用,有几个原因。指针允许控制内存布局(影响CPU缓存的效率)。在Go中,我们可以定义一个结构,其中所有成员都位于连续内存中:


type Point struct {

  x, y int

}


type LineSegment struct {

  source, destination Point

}

在这种情况下,Point结构将嵌入到LineSegment结构中。但是您不能总是直接嵌入数据。如果要支持二进制树或链表之类的结构,则需要支持某种指针。


type TreeNode {

  value int

  left  *TreeNode

  right *TreeNode

}

Java,Python等不存在此问题,因为它不允许您嵌入复合类型,因此无需在语法上区分嵌入和指向。


使用Go指针解决的Swift / C#结构问题

实现此目标的一种可能替代方法是像C#和Swift一样区分struct和class。但这确实有局限性。虽然通常可以指定函数将结构体作为inout参数来避免复制该结构体,但是它不允许您存储对结构体的引用(指针)。这意味着当您发现一个有用的结构(例如,创建池分配器)时,就永远不能将其视为引用类型。


自定义内存分配器

使用指针,您还可以创建自己的池分配器(这非常简化,删除了许多检查以仅显示原理):


type TreeNode {

  value int

  left  *TreeNode

  right *TreeNode


  nextFreeNode *TreeNode; // For memory allocation

}


var pool [1024]TreeNode

var firstFreeNode *TreeNode = &pool[0] 


func poolAlloc() *TreeNode {

    node := firstFreeNode

    firstFreeNode  = firstFreeNode.nextFreeNode

    return node

}


func freeNode(node *TreeNode) {

    node.nextFreeNode = firstFreeNode

    firstFreeNode = node

}

交换两个值

指针还允许您实现swap。那就是交换两个变量的值:


func swap(a *int, b *int) {

   temp := *a

   *a = *b

   *b = temp

}

结论

Java从未能够完全取代C ++在诸如Google之类的地方进行系统编程,部分原因是由于缺乏控制内存布局和使用的能力而无法将性能调整到相同的程度(高速缓存未命中会严重影响性能)。Go旨在在许多领域取代C ++,因此需要支持指针。


查看完整回答
反对 回复 2021-04-26
?
jeck猫

TA贡献1909条经验 获得超7个赞

引用不能重新分配,而指针可以。仅此一项就使指针在无法使用引用的许多情况下很有用。


查看完整回答
反对 回复 2021-04-26
  • 3 回答
  • 0 关注
  • 443 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信