golang method

method:

When a function is declared, put a variable before its name, which is a method. This additional parameter attaches the function to the type, which is equivalent to defining an exclusive method for the type.

package main

import "math"

type Point struct {
    X,Y float64
}

func Distance(p, q Point) float64 {
    return math.Hypot(q.X - p.X, q.Y - p.Y)
}

// method of type Point 
func (p Point) Distance(p, q Point) float64 {
     return math.Hypot(qX - pX, qY - pY)
}

The additional parameter p in the above code is called the receiver of the method. The legacy of early object-oriented languages ​​will call a method called "send a message to an object".

Go differs from many other object-oriented languages ​​in being able to define methods for arbitrary types. So in Go, it's convenient for us to define some additional behavior for some simple numbers, strings, slices, and maps. Methods can be declared to any type, as long as it is not a pointer or an interface .

Pointer-based methods

When a function is called, each parameter value is copied. If a function needs to update a variable, or one of the parameters of the function is too large, we want to avoid this default copy. In this case, we will Need to use pointers. Corresponding to the method we use to update the receiver's object, when the receiver variable itself is relatively large, we can use its pointer instead of the object to declare the method, as follows:

func (p *Point) ScaleBy(factor float64){
    p.X *= factor
    pY *= factor
}

The name of this method is (*Point).ScaleBy . The parentheses here are required; without parentheses the expression might be interpreted as *(Point.ScaleBy).

In real programs, it is generally agreed that if the Point class has a pointer as a receiver method, then all Point methods must have a pointer receiver, even those functions that do not need this pointer receiver.

Only types ( Point ) and pointers to them ( *Point ) are the two types of receivers that may appear in a receiver declaration. In addition, to avoid ambiguity, when declaring a method, a type name that is itself a pointer is not allowed to appear in the receiver, such as the following example:

type P *int
func(P) f() { /*   */ }   //compile err

To call a pointer type method (*Point).ScaleBy , just provide a pointer of type Point, like this:

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

If the receiver p is a variable of type Point, and its method requires a Point pointer as the receiver, we can use the following shorthand:

p.ScaleBy(2)

The compiler will implicitly help us call the ScaleBy method with &p. This shorthand only applies to "variables" , including fields in structs such as pX, and elements in arrays and slices such as perim[0]. We can't call pointer methods through a receiver that can't get the address, such as the memory address of a temporary variable:

Point{1, 2}.ScaleBy(2)    // compile error: can't take address of Point literal

in conclusion:

1. No matter whether the receiver of your method is a pointer type or a non-pointer type, it can be called through a pointer/non-pointer type, and the compiler will do the type conversion for you. 2. When declaring whether the receiver of a method is a pointer or a non-pointer type, you need to consider the internals of two aspects. The first aspect is whether the object itself is particularly large. If it is declared as a non-pointer variable, the call will generate a copy. ; The second aspect is that if you use a pointer type as receiver, then you must pay attention that this pointer type always points to a memory address, even if you copy it. Those who are familiar with C or C fuck should understand quickly here.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326352770&siteId=291194637