Golang pointers

后端 未结 5 682
眼角桃花
眼角桃花 2020-12-23 17:44

I am currently learning to program with Go language. I am having some difficulties understanding Go pointers (and my C/C++ is far away now...). In the Tour of Go #52 (http:/

相关标签:
5条回答
  • 2020-12-23 18:05

    There are two different rules of the Go language used by your examples:

    1. It is possible to derive a method with a pointer receiver from a method with a value receiver. Thus func (v Vertex) Abs() float64 will automatically generate an additional method implementation:

      func (v Vertex) Abs() float64 { return math.Sqrt(v.X*v.X+v.Y*v.Y) }
      func (v *Vertex) Abs() float64 { return Vertex.Abs(*v) }  // GENERATED METHOD
      

      The compiler will automatically find the generated method:

      v := &Vertex{3, 4}
      v.Abs()  // calls the generated method
      
    2. Go can automatically take the address of a variable. In the following example:

      func (v *Vertex) Abs() float64 { return math.Sqrt(v.X*v.X+v.Y*v.Y) }
      func main() {
          v := Vertex{3, 4}
          v.Abs()
      }
      

      the expression v.Abs() is equivalent to the following code:

      vp := &v
      vp.Abs()
      
    0 讨论(0)
  • 2020-12-23 18:14

    The difference is pass-by-referenve vs pass-by-value.

    In func f(v Vertex) the argument is copied into parameter v. In func f(v *Vertex) a pointer to an existing Vertex instance is passed.

    When using methods, some of the dereferencing can be done for you, so you can have a method func (v *Vertex) f() and call it without taking a pointer first: v := Vertex{...}; v.f(). This is just a grain of syntax sugar, AFAIK.

    0 讨论(0)
  • 2020-12-23 18:15

    There are two main differences in those examples:

    func (v *Vertex) Abs()....
    

    The receiver will be passed-by-reference for v and you would be able to call this method only on pointers:

    v := Vertex{1,3}
    v.Abs() // This will result in compile time error
    &v.Abs() // But this will work
    

    On the other hand

    func (v Vertex) Abs() ....
    

    You can call this method on both pointers and structs. The receiver will be passed-by-value even when you call this method on pointers.

    v := Vertex{1,3}
    v.Abs() // This will work, v will be copied.
    &v.Abs() // This will also work, v will also be copied.
    

    You can declare both func (v *Vertex) and func (v Vertex).

    0 讨论(0)
  • 2020-12-23 18:23

    There are differences. For example, the non-pointer receiver form forces the method to work on a copy. This way the method is not able to mutate the instance it was invoked on - it can access only the copy. Which might be ineffective in terms of e.g. time/memory performance/consumption etc.

    OTOH, pointer to instances and methods with pointer receivers allow for easy instance sharing (and mutating) where desirable.

    More details here.

    0 讨论(0)
  • 2020-12-23 18:24

    As the specification says

    A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m():

    In your case v.Abs() is shorthand for &v.Abs() if method is addressable.

    0 讨论(0)
提交回复
热议问题