preface

Many object-oriented languages have similar interface concepts, but the interface type in Go is unique in that it is implemented implicitly and doesn’t need to be written out like Java does

Implementation and use of interfaces

A type implements an interface if it has all the methods that an interface needs.

Excerpt – Novice programming

/* Define the interface */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]}

/* Define the XXX data structure type */
type struct_name xxx

/* Implement the interface method */
func (struct_name_variable struct_name) method_name1(a) [return_type] {
   The /* method implements */}...func (struct_name_variable struct_name) method_namen(a) [return_type] {
   The /* method implements */}
Copy the code

A case study

package main

import "fmt"

type Animal interface {
	run() string
	fly() string
	eat() string
}

// Define the structure
type Dog struct {
	name string
	age  int
}

func (dog Dog) fly(a) string {
	fmt.Println("Dog's name is", dog.name, "He cannot fly.Because he is dog,dog cannot fly ")
	return ""
}

// Implement the interface
func (dog Dog) run(a) string {
	fmt.Println("Dog's name is", dog.name, "He can run. He is", dog.age, "Old")
	return ""
}
func (dog Dog) eat(a) string {
	fmt.Println("Dog's name is", dog.name, "He can eat. He is", dog.age, "Old")
	return ""
}

func main(a) {
	var animal Animal
	dog := Dog{"dog".12}
	animal = dog
	animal.run()
	animal.eat()
	animal.fly()
}

Copy the code

The results of

Dog'Name is dog He can run. He is 12 years old.'s name is dog He can eat. He is 12Old Dog's name is dog He cannot fly.Because he is dog,dog cannot fly 
Copy the code

Interface polymorphism

package main

import "fmt"

type Animal interface {
	fly() string
}

// Define the structure
type Dog struct {
	name string
	age  int
}

// Define the structure
type Bird struct {
	name string
	age  int
}

// a function that takes an interface
func animalFly(animal Animal)  {
	animal.fly()
}

func (dog Dog) fly(a) string {
	fmt.Println("Dog's name is", dog.name, "He cannot fly.Because he is dog,dog cannot fly ")
	return ""
}

func (bird Bird) fly(a) string {
	fmt.Println("Bird's name is", bird.name, "she can fly.Because he is bird,bird can fly ")
	return ""
}

func main(a) {
	dog := Dog{"dog".12}
	bird := Bird{"bird".10}
	animalFly(dog)
	animalFly(bird)
}

Copy the code

The results of

Dog's name is dog He cannot fly.Because he is dog,dog cannot fly Bird's name is bird she can fly.Because he is bird,bird can fly
Copy the code

Embedding of interfaces

Go interfaces are very well supported for embedding. Interfaces can be embedded into other interfaces as if methods of the embedded interface were added directly to the interface.

type Dog interface {
   run()
}
type Bird interface {
   fly()
}

type Animal interface {
   Dog 
   Bird 
}
Copy the code

The above two cases are not difficult, you will basically understand the general operation of the interface.

Standard interface library in Go

  • FMT. Stringer interface

Formatted print

// Stringer is implemented by any value that has a String method,
// which defines the ``native'' format for that value.
// The String method is used to print values passed as an operand
// to any format that accepts a string or to an unformatted printer
// such as Print.
type Stringer interface {
   String() string
}
Copy the code
package main

import "fmt"

type Dog struct {
	name string
	age  int
}

func (dog Dog)String(a)string  {
	return fmt.Sprintf("%s---%v",dog.name,dog.age)

}
func main(a) {
	fmt.Println(Dog{"dog".12})  // dog---12
}

Copy the code
  • Sort. Interface Interface

The sort. sort function of the Go language uses an Interface type sort.Interface to specify the convention between the common sorting algorithm and the types of sequences that can be sorted

package sort

type Interface interface {
	Len() int
	Less(i,j int) bool
	Swap(i, j int)}Copy the code

This case from [go language Chinese — linkanyway] studygolang.com/articles/15…

package main

import (
	"fmt"
	"sort"
	"time"
)

type Track struct {
	Title  string
	Artist string
	Album  string
	Year   int
	Length time.Duration
}

type Tracks []Track

func ParseDurationTime(s string) time.Duration {
	d, err := time.ParseDuration(s)
	iferr ! =nil {
		return ParseDurationTime("0s")}else {
		return d
	}
}

// {{{ implementation of Sort interface
// Len is the number of elements in the collection.
func (x Tracks) Len(a) int {
	return len(x)
}

// Less reports whether the element with
// index i should sort before the element with index j.
func (x Tracks) Less(i, j int) bool {
	return x[i].Year < x[j].Year
}

// Swap swaps the elements with indexes i and j.
func (x Tracks) Swap(i, j int) {
	x[i], x[j] = x[j], x[i]
}

// end implementation of Sort interface }}}

var tracks = Tracks{
	{Title: "C#", Artist: "Delu", Album: "Reading", Year: 2017, Length: ParseDurationTime("3m38s")},
	{Title: "Go", Artist: "Anderson", Album: "Reading", Year: 2018, Length: ParseDurationTime("3m38s")},

	{Title: "Java Bible", Artist: "Js", Album: "Reading", Year: 2016, Length: ParseDurationTime("3m38s")}}

//main function
func main(a) {

	sort.Sort(tracks)

	for key, value := range tracks {
		fmt.Printf("%v:%v \n", key, value)
	}
}
Copy the code

The results of

0:{Java Bible Js Reading 2016 3m38s} 
1:{C# Delu Reading 2017 3m38s} 
2:{Go Anderson Reading 2018 3m38s} 
Copy the code
  • Errors. The error interface

Calling errors.New is very rare because there is a handy wrapper function, FMT.Errorf, which also handles string formatting

The easiest way to create an error is to call errors.New, which returns a New error based on the incoming error information. The entire Errors package is just four lines:

package errors

// New returns an error that formats as the given text.
// Each call to New returns a distinct error value even if the text is identical.
func New(text string) error {
	return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
	s string
}

func (e *errorString) Error(a) string {
	return e.s
}

Copy the code

Type assertion in Go

Syntax for assertion types: x.(T), where x represents the type of an interface and T represents a type (or interface type). There are two possibilities

  • First, if the type T of the assertion is a concrete type, then the type assertion checks whether x’s dynamic type is the same as T’s. If this check succeeds, the result of the type assertion is the dynamic value of X, which of course is of type T. In other words, a type assertion of a concrete type gets a concrete value from the object on which it operates. If the check fails, the next operation throws panic. Such as:

Example from — The Go Program Language

	var w io.Writer
	w = os.Stdout
	f := w.(*os.File) // success f == os.Stdout
	c := w.(*byte.Buffer) // panic: interface holds *os.File, not *bytes.Buffer
Copy the code
  • Second, if the asserted type T is an interface type, the type assertion X.(T) checks whether the dynamic type of X satisfies the T interface. If this check succeeds, the dynamic type and dynamic value of the checked interface value remain unchanged, but the type of the interface value is converted to interface type T. In other words, a type assertion on an interface type changes the way the type is expressed, changes the set of methods available (usually larger), but it protects the dynamic type and value parts inside the interface value.

If the check fails, the next operation will throw panic unless two variables are used to receive the check result, such as f, OK := w.(IO.ReadWriter)

	var w io.Writer
	w = os.Stdout
	rw := w.(io.ReadWriter) // success:	*os.File has both Read and	Write
	w = new(ByteCounter)
	rw = w.(io.ReadWriter) // panic: *ByteCounter has no	Read method
Copy the code

Tip: If the asserted operation object X is a nil interface value, the type assertion will fail regardless of what type T is asserted.

package main

import (
	"fmt"
)

/ / = = = = = = = = interface
type Tester interface {
	getName() string
}
type Tester2 interface {
	printName()
}

/ / = = = = = = = the Person type
type Person struct {
	name string
}

func (p Person) getName(a) string {
	return p.name
}
func (p Person) printName(a) {
	fmt.Println(p.name)
}

/ / = = = = = = = = = = = =
func main(a) {

	var t Tester
	t = Person{"xiaohua"}
	check(t)
}
func check(t Tester) {
	// The first case
	if f, ok1 := t.(Person); ok1 {
		fmt.Printf("%T %s\n", f, f.getName())
	}
	// The second case
	if t, ok2 := t.(Tester2); ok2 { // Reuse variable name t (no need to redeclare)
		check2(t) // If the type assertion is true, the new t is converted to the Tester2 interface type, but its dynamic type and dynamic value remain unchanged}}func check2(t Tester2) {
	t.printName()
}

Copy the code

The results of

main.Person  xiaohua
xiaohua
Copy the code

—- those on TV slam the door and go not to lock the door because they basically don’t come back, so I never watch TV series, just look at the lines I can guess who died in a few episodes.