methods

Method declaration: a method is declared by putting a variable before the name of a function. This additional argument attaches the function to the type, which defines an exclusive method for that type.

The additional parameter p in the following code is called the receiver for the method.

package geometry

import "math"

type Point struct{ X, Y float64 }

// traditional function
func distance(p, q Point) float64 {
    return math.Hypot(q.X-p.X, q.Y-p.Y)
}

// same thing, but as a method of the Point type
func (p Point) distance(q Point) float64 {
    return math.Hypot(q.X-p.X, q.Y-p.Y)
}
Copy the code

Method call:

p := Point{1.2}
q := Point{4.6}
fmt.Println(Distance(p, q)) // "5", function call
fmt.Println(p.Distance(q))  // "5", method call
Copy the code

Pointer object based methods

We can declare methods with Pointers instead of objects

func (p *Point) ScaleBy(factor float64) {
    p.X *= factor
    p.Y *= factor
}
Copy the code

When declaring methods, a type name is not allowed in the sink if it is itself a pointer

type P *int
func (P) f(a) { / *... * / } // compile error: invalid receiver type
Copy the code

Call the pointer type method (*Point).scaleby by providing a pointer to Point

// plan1
r := &Point{1.2}
r.ScaleBy(2)
fmt.Println(*r) {2, 4} "/ /"

// plan2
p := Point{1.2}
pptr := &p
pptr.ScaleBy(2)
fmt.Println(p) {2, 4} "/ /"

//plan3
p := Point{1.2}
(&p).ScaleBy(2)
fmt.Println(p) {2, 4} "/ /"
Copy the code

However, the latter two methods are somewhat unwieldy. Fortunately, the go language itself helps us in places like this. If the sink p is a variable of type Point, and the method requires a Point pointer as the sink, we can write it briefly as follows:

p.ScaleBy(2)
Copy the code

The compiler implicitly helps us call the ScaleBy method with &p. This shorthand applies only to “variables”, including struct fields such as p.X and elements in array and slice such as perim[0]. We cannot call pointer methods from a receiver that cannot fetch an address, such as the memory address of a temporary variable:

Point{1.2}.ScaleBy(2) // compile error: can't take address of Point literal
Copy the code

Extend types by embedding structures

Method values and method expressions

encapsulation