What's the point of having pointers in Go?

前端 未结 4 433
长情又很酷
长情又很酷 2020-12-12 15:45

I know that pointers in Go allow mutation of a function\'s arguments, but wouldn\'t it have been simpler if they adopted just references (with appropriate const or mutable q

4条回答
  •  长情又很酷
    2020-12-12 16:37

    Pointers are usefull for several reasons. Pointers allow control over memory layout (affects efficiency of CPU cache). In Go we can define a structure where all the members are in contiguous memory:

    type Point struct {
      x, y int
    }
    
    type LineSegment struct {
      source, destination Point
    }
    

    In this case the Point structures are embedded within the LineSegment struct. But you can't always embed data directly. If you want to support structures such as binary trees or linked list, then you need to support some kind of pointer.

    type TreeNode {
      value int
      left  *TreeNode
      right *TreeNode
    }
    

    Java, Python etc doesn't have this problem because it does not allow you to embed composite types, so there is no need to syntactically differentiate between embedding and pointing.

    Issues with Swift/C# structs solved with Go pointers

    A possible alternative to accomplish the same is to differentiate between struct and class as C# and Swift does. But this does have limitations. While you can usually specify that a function takes a struct as an inout parameter to avoid copying the struct, it doesn't allow you to store references (pointers) to structs. This means you can never treat a struct as a reference type when you find that useful e.g. to create a pool allocator (see below).

    Custom Memory Allocator

    Using pointers you can also create your own pool allocator (this is very simplified with lots of checks removed to just show the principle):

    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 two values

    Pointers also allows you to implement swap. That is swapping the values of two variables:

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

    Conclusion

    Java has never been able to fully replace C++ for systems programming at places such as Google, in part because performance can not be tuned to the same extend due to the lack of ability to control memory layout and usage (cache misses affect performance significantly). Go has aimed to replace C++ in many areas and thus needs to support pointers.

提交回复
热议问题