Golang interface polymorphism/type assertion

basic introduction


Variables (instances) have many forms. The third major feature of object-oriented, in Go language, polymorphic features are realized through interfaces (interfaces can reflect polymorphic features) . Different implementations can be called according to a unified interface. At this time, the interface variables take on different forms.
In the previous Usb interface case, usb can receive both mobile phone variables and camera variables, which reflects the polymorphic characteristics of the Usb interface. ( Automatically determine what type of variable the USB variable is based on the context )


 

Interface embodies polymorphic characteristics


1) Polymorphic parameters
In the previous Usb interface case, Usb usb can receive both mobile phone variables and camera variables, which reflects the polymorphism of the Usb interface.
2) Polymorphic array
demonstration case: store the Phone structure in the Usb array Body and Camera structure variables, Phone also has a unique method call(), please traverse the Usb array, if it is a Phone variable, in addition to calling the method declared by the Usb interface, you also need to call the Phone-specific method call.

package main

import "fmt"

type Usb interface {
	Working()
}

type Phone struct {
}

type Camera struct {
}

func (*Phone) Working() {
	fmt.Println("phone start working......")
}

func (*Camera) Working() {
	fmt.Println("camera start working......")
}

func test(usb ...Usb) {
	for _, v := range usb {
		v.Working()
	}
}

func main() {
	p := new(Phone)
	c := new(Camera)
	test(p, c)
}

Sometimes it is necessary to make judgments to see what type of variables are passed in and what methods can be used. At this time, you need to use type assertions.

This type cannot be converted blindly. The empty interface does point to the Point type. At the same time, pay attention to whether the = points to the structure variable type or the structure pointer type. 

In fact, it is to convert the empty interface into the corresponding type, then type assertion will be used.

 During type assertion, if there is a mismatch, a panic error will be reported. Therefore, when performing type assertion, make sure that the conversion pointed to by the original null connection type is the type to be asserted. This judgment avoids type assertion failure causing the entire program to crash.

 

 

 Assertion case 1


Add a unique method callo to the Phone structure. When Usb receives the Phone variable, the call method also needs to be called. Walk the code

package main

import "fmt"

type Usb interface {
	Start()
	Stop()
}

type Phone struct {
}

type Camera struct {
}

type Computer struct {
}

func (*Phone) Start() {
	fmt.Println("phone start work.........")
}

func (*Phone) Call() {
	fmt.Println("phone call")
}

func (*Phone) Stop() {
	fmt.Println("phone stop work............")
}

func (*Camera) Start() {
	fmt.Println("camera start work.........")
}

func (*Camera) Stop() {
	fmt.Println("camera stop work.......")
}

func (*Computer) Working(usb ...Usb) {
	for _, v := range usb {
		v.Start()
		if p, ok := v.(*Phone); ok {
			p.Call()
		}
		v.Stop()
	}
}

func main() {
	computer := new(Computer)
	camera := new(Camera)
	phone := new(Phone)

	u := []Usb{camera, phone}
	computer.Working(u...)
}

There is a phone structure here, which has its own unique method. Here, a type assertion is used to first assert whether it is a phone. If the return is OK, the unique method of the structure is called. 

Once the assertion fails, ok returns false, and it will not be executed at all, but it will not affect the operation of the entire program and will not panic.

 

 

Assertion type 2


The number and type of parameters passed in this way are uncertain. 

items ...interface{}

package main

import "fmt"

func TypeJudge(items ...interface{}) {
	for _, v := range items {
		switch v.(type) {
		case bool:
			fmt.Println(v, "type is bool")
		case int64, int:
			fmt.Println(v, "type is int64")
		case string:
			fmt.Println(v, "type is string")
		case float64:
			fmt.Println(v, "type is float64")
		case nil:
			fmt.Println(v, "type is nil")
		default:
			fmt.Println(v, "type is unknown")
		}
	}
}

func main() {
	iFace := []interface{}{1, "hello", 2.3456, true}
	TypeJudge(iFace...)
}

As you can see above, it is possible not only to judge existing types but also to judge custom types.

Guess you like

Origin blog.csdn.net/qq_34556414/article/details/133854105