You can understand the Golang interface of the series at a glance

https://blog.csdn.net/u011957758/article/details/81150622

Preface

Interface is a frequently used move in object-oriented programming, and it is also a very important means to reflect polymorphism.
Yes. There are also interfaces in Golang.

This article will explain Golang's interface in an easy-to-understand way.

After 10s, the following knowledge points are about to reach the battlefield:
1. Why do I need an interface?
2. What is the interface? How to define?
3. First experience of the interface in actual combat
4. How to test whether the interface has been implemented?
5. Empty interface & type assertion
6. Interface zero value
7. One type implements multiple interfaces
8. The difference between pointers and value types implement interfaces
9. Interface nesting

text

1. Why do I need an interface?

In most cases, data may contain different types, but there are one or more common points, these common points are the basis of abstraction. The Golang inheritance mentioned above solves the is-a problem, the single inheritance relationship. But when different parent classes have the same behavior, single inheritance cannot be solved.

Ever since, the interface appeared. Interface can be understood as an abstraction of a certain aspect, which can be many-to-one (multiple types implement an interface), which is also a manifestation of polymorphism . Solved the above one-to-one problem.

2. What is the interface? How to define?

What
interface is a set containing only the method name, parameters, return value is not the specific realization of the collection process .

If all the methods of the interface are implemented, the interface is considered to be implemented, and there is no need to add a statement displayed on the type .

Under this explanation, deepen the impression that the interface in php looks like this:

//定义接口
interface base{
   public function getName();
}
 
//学生类
class student implements base{
   public function getName(){
      echo "咖啡色的羊驼";
   }
}

There is a keyword here: implements .

Such a declaration is called explicit, and in Golang the interface is implemented implicitly . (See below for a foreshadowing)

definition

type interfaceName interface { 
	// 方法列表 
    GetName() string
} 

3. First experience of interface actual combat

In actual programming, everyone likes to end the name of the interface with er. Of course this depends on personal preference.

Above code:

	package main

	import (
		"fmt"
	)
	
	// 定义一个接口
	type People interface {
		ReturnName() string
	}
	
	// 定义一个结构体
	type Student struct {
		Name string
	}
	
	// 定义结构体的一个方法。
	// 突然发现这个方法同接口People的所有方法(就一个),此时可直接认为结构体Student实现了接口People
	func (s Student) ReturnName() string {
		return s.Name
	}
	
	func main() {
		cbs := Student{Name:"咖啡色的羊驼"}
	
		var a People
		// 因为Students实现了接口所以直接赋值没问题
		// 如果没实现会报错:cannot use cbs (type Student) as type People in assignment:Student does not implement People (missing ReturnName method)
		a = cbs       
		name := a.ReturnName() 
		fmt.Println(name) // 输出"咖啡色的羊驼"
	}

4. How to test whether the interface has been implemented?

Use the interface-specific assertion judgment to achieve (will be mentioned again below to deepen the impression).

Syntax: x.(T)
such a grammar is only suitable for x is an interface type

Following the above example, continue with the code:

	// 由于x.(T)只能是接口类型判断,所以传参时候,传入的是接口类型
	// 为何test的类型可以是一个空接口?埋伏笔下文便知。
	func CheckPeople(test interface{}) {
		if _, ok := test.(People); ok {
	    	fmt.Printf("Student implements People")
		}
	}

	
	func main() {
		cbs := Student{Name:"咖啡色的羊驼"}
		CheckPeople(cbs) // Student implements People
	}

5. Empty interface & type assertion

Empty interface

An empty interface is an interface that does not contain any methods. Because of this, all types implement empty interfaces .

Although the empty interface does not play any role, the empty interface is very useful when you need to store any type of value. This also answers the above question, because the empty interface can store any type of data.

	// 定义cbs为空接口
    var cbs interface{}
    var i int = 5
    var s string = "Hello world"
    // cbs可以存储任意类型的数值
    cbs = i
    cbs = s

Type assertion

Since the empty interface can store any type, how to distinguish between different types?
There are two commonly used methods: Comma-ok assertion and switch judgment .

Above code:

	package main
	
	import (
		"fmt"
	)
	
	// 定义一个结构体
	type Student struct {
		Name string
	}
	
	// 类型断言
	func main() {
	    Params := make([]interface{}, 3)
		Params[0] = 88                   // 整型
		Params[1] = "咖啡色的羊驼"         // 字符串
		Params[2] = Student{Name: "cbs"} // 自定义结构体类型
		
		// Comma-ok断言
		for index, v := range Params {
			if _, ok := v.(int); ok {
				fmt.Printf("Params[%d] 是int类型 \n", index)
			} else if _, ok := v.(string); ok {
				fmt.Printf("Params[%d] 是字符串类型\n", index)
			} else if _, ok := v.(Student); ok {
				fmt.Printf("Params[%d] 是自定义结构体类型\n", index)
			} else {
				fmt.Printf("list[%d] 未知类型\n", index)
			}
		}
		
		// switch判断
		for index, v := range Params {
			switch  value := v.(type) {
	        case int:
	            fmt.Printf("Params[%d] 是int类型, 值:%d \n", index,value)
	        case string:
	            fmt.Printf("Params[%d] 是字符串类型, 值:%s\n", index,value)
	        case Student:
	            fmt.Printf("Params[%d] 是Person类型, 值:%s\n", index,value)
	        default:
	            fmt.Printf("list[%d] 未知类型\n", index)
	        } 
		
		}  
	}

6. Interface zero value

The zero value of the interface is nil

	package main
	
	import (
		"fmt"
	)
	
	type People interface {  
	    GetName() string
	}
	
	// 输出 "cbs is nil 类型"
	func main() {  
	    var cbs People
	    if cbs == nil {
	        fmt.Println("cbs is nil 类型")  
	    }
	}

7. One type implements multiple interfaces

	package main
	
	import (
		"fmt"
	)
	
	type People interface {
		ReturnName() string
	}
	
	type Role interface {
		ReturnRole() string
	}
	
	type Student struct {
		Name string
	}
	
	func (s Student) ReturnName() string {
		return s.Name
	}
	
	func (s Student) ReturnRole() string {
		return "学生"
	}
	
	func main() {
		cbs := Student{Name: "咖啡色的羊驼"}
	
		var a People  // 定义a为People接口类型
		var b Role    // 定义b为Role接口类型
		
		a = cbs // 由于Student实现了People所有方法,所以接口实现成功,可直接赋值
		b = cbs // 由于Student实现了Role所有方法,所以接口实现成功,可直接赋值
		
		name := a.ReturnName()
		fmt.Println(name) // 输出"咖啡色的羊驼"
	
		role := b.ReturnRole()
		fmt.Println(role) // 输出"学生"
	}

Also explain one thing: to achieve a certain interface type, there can be other methods. As long as the method implementation includes the interface.

8. The difference between pointer and value type implementation interface

	package main
	
	import (
		"fmt"
	)
	
	type People interface {
		ReturnName() string
	}
	
	type Student struct {
		Name string
	}
	
	type Teacher struct {
		Name string
	}
	
	func (s Student) ReturnName() string {
		return s.Name
	}
	
	func (t *Teacher) ReturnName() string {
		return t.Name
	}
	
	func main() {
		cbs := Student{Name: "咖啡色的羊驼"}
		sss := Teacher{Name: "咖啡色的羊驼的老师"}
	
		// 值类型
		var a People
		a = cbs 
		name := a.ReturnName()
		fmt.Println(name)
	
		// 指针类型
		// a = sss <- 这样写不行!!!
		a = &sss // 由于是指针类型,所以赋值的时候需要加上&
		name = a.ReturnName()
		fmt.Println(name) // 输出"咖啡色的羊驼的老师"
	}

"a = sss" writes like this will cause an error:

	cannot use sss (type Teacher) as type People in assignment:
	Teacher does not implement People (ReturnName method has pointer receiver)

Because the pointer of the Teacher implements the ReturnName method, the Teacher does not implement it.

9. Interface nesting

Similar to PHP's interface inheritance, Golang also has its interface nesting.

	package main
	
	import (
		"fmt"
	)
	
	type People interface {
		ReturnName() string
	}
	
	type Role interface {
		People // 接口嵌套
		ReturnRole() string
	}
	
	type Student struct {
		Name string
	}
	
	func (s Student) ReturnName() string {
		return s.Name
	}
	
	func (s Student) ReturnRole() string {
		return "学生"
	}
	
	
	
	func main() {
		cbs := Student{Name: "咖啡色的羊驼"}
		
		var a Role
		a = cbs 
		name := a.ReturnName()
		fmt.Println(name)
	
		role := a.ReturnRole()
		fmt.Println(role) 
	}

Guess you like

Origin blog.csdn.net/qq_32907195/article/details/112985362