Pointers 什么';围棋中有指针的意义是什么?

Pointers 什么';围棋中有指针的意义是什么?,pointers,go,Pointers,Go,我知道Go中的指针允许函数参数的变异,但如果它们只采用引用(使用适当的常量或可变限定符),不是会更简单吗。现在我们有了指针和一些内置类型,比如映射和通道,隐式地通过引用传递 我是否遗漏了什么,或者围棋中的指针只是一个不必要的复杂问题?引用不能重新分配,而指针可以。这本身就使得指针在许多无法使用引用的情况下非常有用。Go被设计成一种简洁、极简的语言。因此,它只从值和指针开始。后来,由于需要,添加了一些参考类型(切片、贴图和通道) “这个话题有很多历史。早期,映射和通道是语法指针,不可能声明或使

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


我是否遗漏了什么,或者围棋中的指针只是一个不必要的复杂问题?

引用不能重新分配,而指针可以。这本身就使得指针在许多无法使用引用的情况下非常有用。

Go被设计成一种简洁、极简的语言。因此,它只从值和指针开始。后来,由于需要,添加了一些参考类型(切片、贴图和通道)


“这个话题有很多历史。早期,映射和通道是语法指针,不可能声明或使用非指针实例。此外,我们还为阵列的工作方式感到困惑。最终我们决定,指针和值的严格分离使语言更难使用。引入引用类型(包括处理数组引用形式的切片)解决了这些问题。引用类型给语言增加了一些令人遗憾的复杂性,但它们对可用性有很大的影响:当它们被引入时,Go成为了一种更高效、更舒适的语言。”


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


将常量添加到类型系统中会强制其到处显示,并且 如果某个地方发生了变化,则强制将其移到任何地方。在那里 以某种方式将对象标记为不可变可能会有一些好处,但我们不这么认为
我认为常量类型限定符是一个不错的选择。”

我非常喜欢从

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

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

类型点结构{
x、 y整数
}
类型LineSegment结构{
源、目的地
}
在这种情况下,
结构嵌入在
线段
结构中。但您不能总是直接嵌入数据。如果您希望支持二叉树或链表等结构,则需要支持某种类型的指针

类型树节点{
值int
左*树节点
右*树节点
}
Java、Python等没有这个问题,因为它不允许嵌入复合类型,所以不需要在语法上区分嵌入和指向

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

自定义内存分配器 使用指针,您还可以创建自己的池分配器(这非常简单,删除了许多检查,只是为了显示原理):

类型树节点{
值int
左*树节点
右*树节点
nextFreeNode*TreeNode;//用于内存分配
}
变量池[1024]树节点
var firstFreeNode*TreeNode=&pool[0]
func poolAlloc()*树节点{
节点:=firstFreeNode
firstFreeNode=firstFreeNode.nextFreeNode
返回节点
}
func freeNode(节点*TreeNode){
node.nextFreeNode=firstFreeNode
firstFreeNode=node
}
交换两个值 指针还允许您实现
交换
。即交换两个变量的值:

func swap(a *int, b *int) {
   temp := *a
   *a = *b
   *b = temp
}
结论

java从未完全取代C++在谷歌等地方进行系统编程,部分原因是由于无法控制内存布局和使用(缓存命中率显著影响性能),性能无法被调整到相同的扩展。GO的目的是在很多领域取代C++,因此需要支持指针。

这里有一个问题可以帮助澄清:通过值传递引用和通过引用来传递确实有区别。注意:问题是关于java,但它也适用于这里。对于一些内置类型,如映射和通道,隐式传递引用。“不,在Go中,一切都是按值传递的。有些类型是(非正式地称为)引用类型,因为它们具有内部可变状态。这个问题的问题是,“引用”并不是一个具有定义良好属性的单一对象。术语“引用”“非常模糊。我们可以从答案中看出有多少人在“参考”一词中读到了不同的东西。因此,这个问题应该详细说明Go指针和问题所考虑的引用之间的区别。FWIW,Go中的“引用类型”也可以重新分配。它们更像隐式指针?它们只是包含指针(以及长度、容量等)的结构的特殊语法。C#允许通过引用传递结构。请参阅“ref”和“out”关键字。好吧,这就像Swift一样。我会想办法更新我的例子。我不明白第一点,左和右不能就是TreeNode吗?大多数类型化语言不允许递归类型/接口,而不使用指针吗?问题是“为什么我们使用指针而不是引用”,我不明白为什么这个示例不能处理引用。@AndreKR,因为我们可以选择是按引用传递还是按值传递。有一些
func swap(a *int, b *int) {
   temp := *a
   *a = *b
   *b = temp
}