Pointers 传递指针与Go中的值

Pointers 传递指针与Go中的值,pointers,go,Pointers,Go,我读过这篇有趣的文章,它与围棋完全无关。作者说的一句话引起了我的注意,下面这句话: 。。。例如,将通道作为函数all的参数传递是有效的,因为Go中的通道就像指向用C实现的通道数据结构的指针一样简单。map和其他一些类型也是如此。但是传递数组或结构的效率很低;相反,我们应该传递指向这些类型的指针 为什么在使用某些Go内部类型或结构时传递指针效率很低?传递指针效率并不低。但作者是正确的:因为数组和结构在默认情况下是按值传递的,所以它们的内容会复制到每个新函数调用中。这可能是低效的 根据,数组按值传递

我读过这篇有趣的文章,它与围棋完全无关。作者说的一句话引起了我的注意,下面这句话:

。。。例如,将通道作为函数all的参数传递是有效的,因为Go中的通道就像指向用C实现的通道数据结构的指针一样简单。map和其他一些类型也是如此。但是传递数组或结构的效率很低;相反,我们应该传递指向这些类型的指针


为什么在使用某些Go内部类型或结构时传递指针效率很低?

传递指针效率并不低。但作者是正确的:因为数组和结构在默认情况下是按值传递的,所以它们的内容会复制到每个新函数调用中。这可能是低效的

根据,数组按值传递。(切片使用指向引擎盖下阵列的指针,因此它们的传递效率更高。)

与片一样,通道由
make
(至少隐式地)分配,依此类推


因此,在使用结构和实际数组时,通常会传递它们的引用。(有关这方面的更多细节,请参见肖恩的回答。他很好地指出,复制并不总是低效的。有时它是可取的。)

上下文与此相关:

然而,围棋的类型体系是如此复杂;程序员需要知道 有关标准类型实现的所有详细信息,请参见 他们可以正确地使用它们。例如,它是有效的

作者说,贴图和通道看起来像值,但在复制时像指针

对于其他数据类型,参数中有一个
*
,这是一个清晰的信号,可以对其进行适当修改。通常,参数的前面也有一个
&
,这是另一个参数正在修改的信号

当传递贴图和通道时,这些语法信号不存在。这会导致像这样的意外结果:

类似的批评也适用于像
[256]byte
这样的数组和像
[]byte
这样的片之间的巨大差异,其中缺少大小是不同复制行为的唯一信号

抛开所有这些不谈,作者错误地将复制效率低下等同起来。的确,复制有时需要比传递指针更多的CPU周期或内存访问。然而,情况并非总是如此。它取决于结构的大小和编译器执行的优化

复制(即传递值)与传递指针的决定也与函数是否修改参数有关


对于不打算由函数修改的小型结构和数组,按值传递它们。这消除了由于意外修改而导致的一整类错误,甚至比其他语言中使用的
const
更好,因为没有办法欺骗和绕过它。当然,在使用嵌入式指针时一定要小心,包括映射和切片,因为这些指针仍可能在函数内部被修改。

谢谢您提供的详细答案。非常感谢。