Go study notes (71) — Go interface interface (interface definition, interface implementation, interface call, value receiver, pointer receiver)

1. Definition of the interface

An interface is an agreement with the caller. It is a highly abstract type and does not need to be tied to specific implementation details. Interface to do is to define good convention, tell the caller what they can do, but do not know its internal implementation, which we have seen and the specific type, such as int, map, sliceetc. are not the same.

Define and structure the interface is slightly different, though all to typebegin the keyword, but the keyword interface is interfacerepresenting the type of a custom interface.

That personis an interface, which has two methods sayName() stringand sayAge() int, as a whole shown in the following code:

type person interface {
    
    
	sayName() string
	sayAge() int
}
}

For personthe interface, it will tell the caller through its sayName()acquisition method name string, through its sayAge()acquisition of age method, which is the agreed interface. As for how the string is obtained and what it looks like, the interface does not care, and the caller does not need to care, because these are done by the implementer of the interface.

2. Implementation of the interface

Interface must be implemented by a particular type to studentthe structure, for example,

type student struct {
    
    
	name string
	age  int
}

It is achieved personinterfaces, as shown in the following code:

func (s student) sayName() string {
    
    
	fmt.Printf("name is %v\n", s.name)
	return s.name
}

func (s student) sayAge() int {
    
    
	fmt.Printf("name is %v\n", s.age)
	return s.age
}

Type structure to studentdefine a method that in the method signature, and an interface (name, parameters and return values) the same, so the structure studentis realized personinterface.

Note: If an interface has multiple methods, then each method that needs to implement the interface is considered to implement the interface.

3. Interface Assignment

Interface assignment Godivided into the following two situations languages:

  • Assign the object instance to the interface;
  • Assign one interface to another interface.

3.1 Assign object instance to interface

First discuss the assignment of a certain type of object instance to the interface, which requires the object instance to implement all the methods required by the interface, as follows:

type Integer int

func (a Integer) Less(b Integer) bool {
    
    
	return a < b
}

func (a *Integer) Add(b Integer) {
    
    
	*a += b
}

Correspondingly, we define the interface LessAdderas follows:

type LessAdder interface {
    
    
	Less(b Integer) bool
	Add(b Integer)
}

Now there is a question: Suppose we define an Integerobject instance types, how to assign it to LessAdderthe interface it?
Should I use the following statement (1) or statement (2)?

var a Integer = 1
var b LessAdder = &a ... (1)
var b LessAdder = a ... (2)

The answer is that the sentence (1) should be used. The reason is that the Golanguage can be based on the following functions:

func (a Integer) Less(b Integer) bool {
    
    
	return a < b
}

Automatically generate a new Less()method:

func (a *Integer) Less(b Integer) bool {
    
    
	return (*a).Less(b)
}

Thus, the type *Integerexists both Less()methods, there are Add()methods to meet LessAdderthe interface.
On the other hand, according to

	func (a *Integer) Add(b Integer)

This function cannot automatically generate the following member method:

func (a Integer) Add(b Integer) {
    
    
	(&a).Add(b)
}

Because (&a).Add()change is only a function of the parameters a, subject to external influence is not practical to operate, which is not consistent with the
expectations of users.

Therefore, the Golanguage does not automatically generate this function for it. Thus, the type Integerthere is only Less()a method, the lack of Add()a method, does not satisfy LessAdderthe interface, therefore the above statements (2) can not be assigned.

To further demonstrate the above reasoning, we may wish to define an Lesserinterface as follows:

type Lesser interface {
    
    
	Less(b Integer) bool
}

Then define an Integerobject instance of type, assign it to Lesserthe interface:

var a Integer = 1
var b1 Lesser = &a ... (1)
var b2 Lesser = a ... (2)

As we expected, both statement (1) and statement (2) can be compiled and passed.

3.2 Assign one interface to another interface

In Golanguage, as long as both interfaces have the same list of methods (different order does not matter), then they are equivalent, can be assigned to each other.

4. Interface call

Implements personthe interface after use. First of all I would like to define a print personfunction interface, as follows:

func printPersonInfo(p person) {
    
    
	fmt.Printf("name is %v\n", p.sayName())
	fmt.Printf("age is %v\n", p.sayAge())
}

This function is defined printPersonInfo, it receives an personinterface type of the parameter, and then print out the personinterface sayName()string returned by the method, sayAge()the method returns Age

printPersonInfoThe advantage of this function is that it is oriented programming interface, as long as a type implements Stringerthe interface, can print out a corresponding character string, and do not control the specific type implementations.

Since studentimplements personthe interface, so variable stuas a function of printPersonInfothe parameters, may be printed in the following manner:

printPersonInfo(stu)

Output

name is wohu
age is 20

Let structure teacheralso implement personan interface, as shown in the following code:

type teacher struct {
    
    
	name string
	age  int
}

func (t teacher) sayName() string {
    
    
	return t.name
}

func (t teacher) sayAge() int {
    
    
	return t.age
}

Since the structure teacheralso implements the personinterface, printPersonInfofunction without any change, it can be directly used, as follows:

printPersonInfo(t)

Output result:

name is Jack
age is 40

This is the benefit of interface-oriented, as long as the definition and caller meet the agreement, you can use it, regardless of the specific implementation. Implementers of the interface can also upgrade and refactor better without any impact, because the interface convention has not changed.

5. Value receiver and pointer receiver

We already know that if you want to implement an interface, you must implement all the methods provided by the interface, and when explaining the method in the last lesson, you define a method, which has two types: value type receiver and pointer type receiver. Both methods can be invoked, because the Gocompiler automatically do the conversion, the value of type pointer and type of recipient receivers are equivalent. But in the implementation of the interface, the receiver of the value type and the receiver of the pointer type are different. I will analyze the difference between the two in detail below.

The above has been verified structure type implements personan interface, then the structure corresponding to the pointer is also implements this interface it? I used the following code to test:

printPersonInfo(&s)

Output result:

name is wohu
age is 20

After testing will find the variable tpointer as an argument passed to printPersonInfothe function are possible, compile and run are normal. This proves that when a value type receiver implements an interface, both the type itself and the pointer type of the type implement the interface.

Example recipient median ( s student) implements personthe interface, the type studentand pointer type it *studentwould have achieved personthe interface.

Now, I change the receiver to a pointer type, as shown in the following code:

func (s *student) sayName() string {
    
    
	return s.name
}

func (s *student) sayAge() int {
    
    
	return s.age
}

Pointer type receiver modified to find example line printPersonInfo(stu)code compilation is not passed, suggesting the following errors:

demo.go:46:17: cannot use stu (type student) as type person in argument to printPersonInfo:
	student does not implement person (sayAge method has pointer receiver)

Meaning that the type studentdoes not implement personthe interface. This proves that when a pointer type receiver implements an interface, only the corresponding pointer type is considered to implement the interface.

to sum up:

  • When the value type as the recipient, studenttype and *studenttype implements this interface;

  • When the pointer type as the receiver, only *studentthe type implements this interface;

It can be found that there are types that implement interfaces *student, which also shows that the pointer type is more versatile, no matter which kind of receiver, it can implement the interface.

package main

import "fmt"

type student struct {
    
    
	name string
	age  int
}

type teacher struct {
    
    
	name string
	age  int
}

type person interface {
    
    
	sayName() string
	sayAge() int
}

func (t teacher) sayName() string {
    
    
	return t.name
}

func (t teacher) sayAge() int {
    
    
	return t.age
}

func (s *student) sayName() string {
    
    
	// fmt.Printf("name is %v\n", s.name)
	return s.name
}

func (s *student) sayAge() int {
    
    
	// fmt.Printf("age is %v\n", s.age)
	return s.age
}

func printPersonInfo(p person) {
    
    
	fmt.Printf("name is %v\n", p.sayName())
	fmt.Printf("age is %v\n", p.sayAge())
}

func main() {
    
    
	stu := student{
    
    name: "wohu", age: 20}
	// t := teacher{name: "Jack", age: 40}
	printPersonInfo(stu)
	// printPersonInfo(t)

}

Guess you like

Origin blog.csdn.net/wohu1104/article/details/111242632