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

ano*_*non 86 pointers go

我知道Go中的指针允许函数参数的变异,但如果它们只采用引用(使用适当的const或可变限定符),它就不会更简单.现在我们有指针和一些内置类型,如地图和通道隐式传递引用.

我是否遗漏了某些内容或指向Go只是一个不必要的并发症?

Pio*_*ski 37

我非常喜欢http://www.golang-book.com/8上的例子

func zero(x int) {
    x = 0
}
func main() {
    x := 5
    zero(x)
    fmt.Println(x) // x is still 5
}
Run Code Online (Sandbox Code Playgroud)

与...相对照

func zero(xPtr *int) {
    *xPtr = 0
}
func main() {
    x := 5
    zero(&x)
    fmt.Println(x) // x is 0
}
Run Code Online (Sandbox Code Playgroud)

  • 问题是"为什么我们有指针**而不是引用**"我不明白为什么这个例子不适用于引用. (28认同)
  • @DJMethaneMan这是"指针与参考",而不是"指针与传递价值"! (7认同)
  • 我不明白为什么 Go 应该是最简单的流行语言之一,但它们却包含这样的“功能”......这很令人困惑,而且似乎没有必要,至少对于在这里指出这一点的人来说。 (4认同)

zil*_*n01 31

无法重新分配引用,而指针可以.仅这一点使指针在许多不能使用引用的情况下有用.

  • 引用是否可重新分配是特定于语言的实现问题. (14认同)

Eri*_*eim 30

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

type Point struct {
  x, y int
}

type LineSegment struct {
  source, destination Point
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Point结构嵌入在LineSegment结构中.但是你不能总是直接嵌入数据.如果要支持二叉树或链表等结构,则需要支持某种指针.

type TreeNode {
  value int
  left  *TreeNode
  right *TreeNode
}
Run Code Online (Sandbox Code Playgroud)

Java,Python等没有这个问题,因为它不允许嵌入复合类型,因此不需要在语法上区分嵌入和指向.

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

一种可能的替代来完成相同的是区分structclassC#和夫特一样.但这确实有局限性.虽然您通常可以指定函数将结构作为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
}
Run Code Online (Sandbox Code Playgroud)

交换两个值

指针也允许您实施swap.这是交换两个变量的值:

func swap(a *int, b *int) {
   temp := *a
   *a = *b
   *b = temp
}
Run Code Online (Sandbox Code Playgroud)

结论

Java从来没有能够在谷歌这样的地方完全取代C++用于系统编程,部分原因是由于缺乏控制内存布局和使用的能力而无法将性能调整到相同的范围(缓存未命中会显着影响性能).Go的目标是在许多领域取代C++,因此需要支持指针.

  • C#允许通过引用传递结构.请参阅"ref"和"out"关键字. (6认同)

pet*_*rSO 27

Go旨在成为一种简洁,极简主义的语言.因此,它始于值和指针.之后,根据需要,添加了一些参考类型(切片,地图和通道).


Go编程语言:语言设计常见问题解答:为什么在数组是值时引用地图,切片和通道?

"在这个主题上有很多历史.早期,地图和通道都是语法指针,不可能声明或使用非指针实例.而且,我们在数组如何工作方面也很困难.最终我们决定严格分离指针和值使得语言难以使用.引入引用类型,包括处理数组引用形式的切片,解决了这些问题.引用类型为语言增加了一些令人遗憾的复杂性,但它们对可用性有很大影响:Go成为了引入时更高效,更舒适的语言."


快速编译是Go编程语言的主要设计目标; 这有其成本.其中一个伤员似乎是将变量(基本编译时常量除外)和参数标记为不可变的能力.已被要求,但拒绝了.


golang-nuts:去语言.一些反馈和怀疑.

"将const添加到类型系统会强制它出现在任何地方,并强制一个人在任何地方发生变化时将其删除.虽然以某种方式标记对象不可变可能会有一些好处,但我们认为const类型限定符不是这样的去吧."