我知道 Go 中的指针允许改变函数的参数,但如果只引用(使用适当的 const 或可变限定符),它会更简单吗?现在我们有指针和一些内置类型,如映射和通道隐式引用传输。+ Z/ Z$ O" z$ p* Q# Y0 G9 s
我错过了什么,还是 Go 指针只是不必要的并发症? & p2 ]4 u3 N5 J0 b. H * ] ~& R! S7 P. u% u 解决方案: 2 L/ k/ }& e5 H. d! e 指针有用的原因有几个。指针允许控制内存布局(影响 CPU 缓存效率)。Go 我们可以定义一个结构,所有成员都在连续内存中:. D" H, e( ? O) u5 G D- h# {7 L
type Point struct { x,y int}type LineSegment struct { source,destination Point} 2 F4 A+ R) K9 \# ]. j, Q
在这种情况下,Point结构嵌入在LineSegment在结构中。但是你不能总是直接嵌入数据。要支持二叉树或链表等结构,需要支持指针。 k3 \$ S& a9 P" x& K
type TreeNode { value int left *TreeNode right *TreeNode} 2 f4 Y& C( N+ K; U# D7 Z- e2 _
Java、Python 没有这个问题,因为它不允许你嵌入复合类型,所以你不需要区分语法上的嵌入和方向。 & G2 Y+ M6 e' d8 [. [: x+ L使用 Go 指针解决 Swift/C# 结构问题可能的替代方法是区分相同的目的C# 和 Swiftstruct并class按照 C# 和 Swift 区分的方式。但这确实有局限性。虽然你通常可以指定函数将结构作为结构inout参数避免复制结构,但不允许您存储结构引用(指针)。这意味着当您发现该结构对创建池分配器(见下文)有用时,您永远不能将其视为引用类型。: {6 Z! }8 j) {2 A3 |
定制内存分配器使用指针,您还可以创建自己的池分配器(这是非常简单的,删除大量检查以显示原理):/ H' {. b. F1 S# P& t/ J
type TreeNode { value int left *TreeNode right *TreeNode nextFreeNode *TreeNode; // For memory allocation}var pool [1024]TreeNodevar firstFreeNode *TreeNode = &pool[0] func poolAlloc() *TreeNode node := firstFreeNode firstFreeNode = firstFreeNode.nextFreeNode return node}func freeNode(node *TreeNode) node.nextFreeNode = firstFreeNode firstFreeNode = node} 2 R+ I6 r5 E' t& d7 q% ?