• 11-Go基础:接口


    一、接口简介

    • 什么是接口
      • 接口就是一种规范与标准,只是规定了要做哪些事情。具体怎么做,接口是不管的
      • 接口把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口

    二、接口的定义与实现

    • 接口定义语法:接口名字我们通常使用“er”结尾
    type 接口名字  interface {
    	方法声明
    }
    
    • 1
    • 2
    • 3
    • 接口实现
      • 为结构体添加接口中的方法
      • 结构体需要完成接口中所有声明的方法
    • 接口方法调用
      • 将结构体的地址赋值给接口对象
      • 通过接口对象调用对应结构体实现的接口方法
    package main
    
    import "fmt"
    
    type Personer interface {
    	SayHello()
    }
    
    type Student struct {
    
    }
    
    func (s *Student) SayHello(){
    	fmt.Println("老师好")
    }
    
    type Teacher struct {
    
    }
    
    func (t *Teacher) SayHello(){
    	fmt.Println("学生好")
    }
    
    func main() {
    	var stu Student
    	var teacher Teacher
    	var person Personer
    	person = &stu
    	person.SayHello()
    	person = &teacher
    	person.SayHello()
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    三、多态定义与实现

    1 - 多态定义实现

    • 什么是多态:所谓多态,指的是多种表现形式;多态就是同一个接口,使用不同的实例而执行不同操作
    • 多态实现:在函数中传递的形参为接口类型
    func 函数名 (参数 接口类型){
    	
    }
    
    • 1
    • 2
    • 3
    package main
    
    import "fmt"
    
    type Personer interface {
    	SayHello()
    }
    
    type Student struct {
    
    }
    
    func (s *Student) SayHello(){
    	fmt.Println("老师好")
    }
    
    type Teacher struct {
    
    }
    
    func (t *Teacher) SayHello(){
    	fmt.Println("学生好")
    }
    
    func WhoSayHi(h Personer)  {
    	h.SayHello()
    }
    
    func main() {
    	var stu Student
    	var teacher Teacher
    	WhoSayHi(&stu)
    	WhoSayHi(&teacher)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    2 - 多态案例:U盘移动硬盘

    • 需求:用多态来模拟实现 将移动硬盘或者U盘插到电脑上进行读写数据
    package main
    
    import "fmt"
    
    type Stroager interface {
    	Read()
    	Write()
    }
    
    // 移动硬盘
    type MDisk struct {
    }
    
    func (m *MDisk) Read() {
    	fmt.Println("移动硬盘读取数据")
    }
    
    func (m *MDisk) Write() {
    	fmt.Println("移动硬盘写入数据")
    }
    
    // U盘
    type UDisk struct {
    }
    
    func (m *UDisk) Read() {
    	fmt.Println("U盘读取数据")
    }
    
    func (m *UDisk) Write() {
    	fmt.Println("U盘写入数据")
    }
    
    func Computer(c Stroager) {
    	c.Read()
    	c.Write()
    }
    
    func main() {
    	var mdisk MDisk
    	var udisk UDisk
    	Computer(&mdisk)
    	Computer(&udisk)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    3 - 多态案例:计算器

    package main
    
    import "fmt"
    
    type Object struct {
    	numA int
    	numB int
    }
    
    type Resulter interface {
    	GetResult() int
    }
    
    type Add struct {
    	Object
    }
    
    type Sub struct {
    	Object
    }
    
    func (a *Add) GetResult() int {
    	return a.numA + a.numB
    }
    
    func (s *Sub) GetResult() int {
    	return s.numA - s.numB
    }
    
    // 假设需求修改,从原先+的需求修改为-
    // 如果使用原来的方法,需要将Add创建对象的方法删除掉,修改为Sub的方法
    // 现在希望在main中尽量少的修改就完成需求实现
    
    //1、定义一个新的类
    //2、创建一个方法,在该方法中完成对象的创建
    
    type OperatorFactory struct {
    }
    
    func (o *OperatorFactory) CreateOperator(op string, numA int, numB int) int {
    	switch op {
    	case "+":
    		add := Add{Object{numA: numA, numB: numB}}
    		return OperatorWho(&add)
    	case "-":
    		sub := Sub{Object{numA: numA, numB: numB}}
    		return OperatorWho(&sub)
    	default:
    		return 0
    	}
    }
    
    func OperatorWho(h Resulter) int {
    	return h.GetResult()
    }
    
    func main() {
    	var operator OperatorFactory
    	num := operator.CreateOperator("-", 10, 5)
    	fmt.Println(num)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    四、接口的继承与转换

    • 接口继承
    package main
    
    import "fmt"
    
    type Humaner interface {
    	SayHello()
    }
    
    type Personer interface {
    	Humaner
    	Say()
    }
    
    type Student struct {
    }
    
    func (s *Student) SayHello() {
    	fmt.Println("大家好")
    }
    
    func (s *Student) Say() {
    	fmt.Println("你好")
    }
    
    func main() {
    	var stu Student
    	var per Personer
    	per = &stu
    	per.Say()
    	per.SayHello() // 可以调用所继承的接口中的方法
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 接口转换
    func main() {
    	var stu Student
    	var per Personer
    	per = &stu
    
    	var h Humaner
    	h = per
    	h.SayHello()
    	//h.Say() 这个是无法调用的
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    五、空接口的定义与使用

    • 什么是空接口:空接口(interface{})不包含任何的方法,正因为如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值
    func main() {
    	var i interface{}
    	i = 123
    	fmt.Println(i)
    	i = "abc"
    	fmt.Println(i)
    
    	//可以存储各种类型数据的切片
    	var s []interface{}
    	s = append(s, 123, "abc", 12.3)
    	for _, value := range s {
    		fmt.Println(value)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    六、类型断言

    • 类型断言:通过类型断言,可以判断空接口中存储的数据类型
    • 类型断言语法:value, ok := m.(T)
      • m:表空接口类型变量
      • T:是断言的类型
      • value: 变量m中的值
      • ok: 布尔类型变量,如果断言成功为true,否则为false
    func main() {
    	var i interface{}
    	i = 123
    	i = "abc"
    	value, ok := i.(int)
    	if ok {
    		fmt.Println(value)
    	} else {
    		fmt.Println("类型推断错误")
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 综合应用:空接口与类型断言
    package main
    
    import "fmt"
    
    type Object struct {
    	numA int
    	numB int
    }
    
    type Resulter interface {
    	GetResult() int
    	SetData(data ...interface{}) bool // 完成参数运算的数据类型的校验
    }
    
    type Add struct {
    	Object
    }
    
    type Sub struct {
    	Object
    }
    
    func (a *Add) GetResult() int {
    	return a.numA + a.numB
    }
    
    func (a *Add) SetData(data ...interface{}) bool {
    	var b bool = true
    	//对数据个数进行校验
    	if len(data) > 2 {
    		b = false
    	}
    	//类型校验
    	value1, ok1 := data[0].(int)
    	if !ok1 {
    		fmt.Println("第一个数类型错误")
    		b = false
    	}
    	value2, ok2 := data[1].(int)
    	if !ok2 {
    		fmt.Println("第二个数类型错误")
    		b = false
    	}
    	a.numA = value1
    	a.numB = value2
    	return b
    }
    
    func (s *Sub) GetResult() int {
    	return s.numA - s.numB
    }
    
    func (s *Sub) SetData(data ...interface{}) bool {
    	var b bool = true
    	//对数据个数进行校验
    	if len(data) > 2 {
    		b = false
    	}
    	//类型校验
    	value1, ok1 := data[0].(int)
    	if !ok1 {
    		fmt.Println("第一个数类型错误")
    		b = false
    	}
    	value2, ok2 := data[1].(int)
    	if !ok2 {
    		fmt.Println("第二个数类型错误")
    		b = false
    	}
    	s.numA = value1
    	s.numB = value2
    	return b
    }
    
    // 假设需求修改,从原先+的需求修改为-
    // 如果使用原来的方法,需要将Add创建对象的方法删除掉,修改为Sub的方法
    // 现在希望在main中尽量少的修改就完成需求实现
    
    //1、定义一个新的类
    //2、创建一个方法,在该方法中完成对象的创建
    
    type OperatorFactory struct {
    }
    
    func (o *OperatorFactory) CreateOperator(op string) Resulter {
    	switch op {
    	case "+":
    		add := new(Add)
    		return add
    	case "-":
    		sub := new(Sub)
    		return sub
    	default:
    		return nil
    	}
    }
    
    func OperatorWho(h Resulter) int {
    	return h.GetResult()
    }
    
    func main() {
    	var operator OperatorFactory
    
    	obj := operator.CreateOperator("-")
    	b := obj.SetData(10, 20)
    	if b {
    		num := OperatorWho(obj)
    		fmt.Println(num)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
  • 相关阅读:
    Python+大数据-Spark技术栈(二)SparkBase&Core
    数据库期末考前复习题(单选+多选+判断+解答)
    运维监控背景信息
    主流的网络计算模式有哪些
    留言墙项目【Vue3 + nodejs + express + mysql】——上
    课程32:.Net Core Web API部署IIS
    数据结构 堆——详细动画图解,形象理解
    黑马点评--优惠卷秒杀
    Java Maven POM配置参考
    KylinOSv10系统k8s集群启动mysql5.7占用内存高的问题
  • 原文地址:https://blog.csdn.net/qq23001186/article/details/125510397