Golang primer (2) : methods and interfaces

  • 2020-05-07 19:52:51
  • OfStack

method

There are no classes in Golang, but we can define methods for structs. Let's take a look at an example:


package main
 
import (
    "fmt"
    "math"
)
 
type Vertex struct {
    X, Y float64
}
 
// The structure of the body Vertex The method of
// Here's the method receiver ( method receiver ) v The type of *Vertex
func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
 
func main() {
    v := &Vertex{3, 4}
    fmt.Println(v.Abs())
}

Here the receiver of the method USES the pointer type instead of the value type mainly for the following reasons (languages like C/C++) :

1. Avoid unnecessary copies of the receiver each time the method is called
2. The value of the receiver can be changed within the method

We can define methods for any type except:

1. You cannot define a method for a type if it is defined in another package
2. You cannot define a method for a type if it is a base type


package main
 
import (
    "fmt"
    "math"
)
 
// define 1 A type of MyFloat
type MyFloat float64
 
// Note that the method is associated with a type of MyFloat Rather than *MyFloat
func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}
 
func main() {
    f := MyFloat(-math.Sqrt2)
    fmt.Println(f.Abs())
}

interface (interface)

Interfaces are also of type 1 (just like struct 1). An interface type contains a set of methods, and an interface type can hold values that implement those methods. Example:


// Defines the interface Abser
type Abser interface {
    Abs() float64
}
 
// Defining structure Vertex
type Vertex struct {
    X, Y float64
}
 
// Implementation method Abs
func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
 
func main() {
    v := Vertex{3, 4}
    // Success, can hold *Vertex The value of the type
    var a Abser = &v
    // Error, cannot hold Vertex The value of the type
    // Because in the *Vertex Methods are defined on Abs , but not in Vertex Defined on the
    var b Abser = v
}

error

Golang provides an error interface:


type error interface {
    Error() string
}

We use the os.Open function to understand the usage of error:


// This function is used to open 1 A file
// Returns the first 2 A value of error type
func Open(name string) (file *File, err error)

Simple example:


package main
 
import (
    "fmt"
    "os"
)
 
func main() {
    _, err := os.Open("test.txt")
    // if err Don't for nil Indicates an error
    if err != nil {
        fmt.Println(err)
    }
}

The easiest way to create an error value is to use the errors.New function:


func Sqrt(f float64) (float64, error) {
    if f < 0 {
        // Error return 1 A mistake
        return 0, errors.New("math: square root of negative number")
    }
    // ...
}

We can also define a new implementation of error (that is, the implementation interface error) :

type NegativeSqrtError float64
 
func (f NegativeSqrtError) Error() string {
    return fmt.Sprintf("math: square root of negative number %g", float64(f))
}

anonymous field

Fields with only types and no names can exist in a structure, and they are called anonymous fields. Such as:


struct {
    T1
    *T2
}

The domain or method in the anonymous domain of a struct can be accessed directly by this struct instance:


package main
 
import "fmt"
 
type Car struct {
    wheelCount int
}
 
func (car *Car) numberOfWheels() int {
    return car.wheelCount
}
 
type Ferrari struct {
    Car
}
 
func main() {
    f := Ferrari{Car{4}}
    fmt.Println("A Ferrari has this many wheels: ", f.numberOfWheels())
}


Related articles: