Go-21 Golang接口详解

package main

import "fmt"

// Golang 中的接口详解
/*
	1.接口的介绍
	2.Golang接口的定义
	3.空接口
	4.类型断言
	5.结构体值接收者和指针接收者实现接口的区别
	6.一个结构体实现多个接口
	7.接口嵌套
*/

// 实例1:定义一个Usber接口让Phone和Camera结构体实现这个接口

type Usber interface {
	Start()
	Stop()
}

type Phone struct {
	Name string
}

func (p Phone) Start() {
	fmt.Println(p.Name, "开始工作")
}

func (p Phone) Stop() {
	fmt.Println("手机 停止工作")
}

type Camera struct {
}

func (c Camera) Start() {
	fmt.Println("相机开始工作")
}

func (c Camera) Stop() {
	fmt.Println("相机停止工作")
}

// 实例2:Computer 结构体中的Work方法必须传入一个Usb的接口

type Computer struct { // 电脑的结构体
	Name string
}

// 电脑的Work方法必须要求传入Usb接口类型数据
// 【【【	Work中传入的参数就相当于 var usb Usber = 入参	,入参需要是一个结构体的实例,该结构体就实现了Usb接口。	】】】

func (c Computer) Work(usb Usber) {
	usb.Start()
	usb.Stop()
}

// 空接口
func show(a interface{}) {
	fmt.Printf("值:%v  类型:%T \n", a, a)
}

// 值接收者

type UsbValue interface {
	start()
	stop()
}
type Fan struct { // 风扇结构体
	Name string
}

func (f Fan) start() {
	fmt.Println(f.Name, "开始工作")
}

func (f Fan) stop() {
	fmt.Println("风扇 停止工作")
}

// 指针接收者

type UsbPointer interface {
	run()
	skip()
}

type Rabbit struct { // 风扇结构体
	Name string
}

func (r *Rabbit) run() {
	fmt.Println(r.Name, "真可爱,跑起来")
}

func (r *Rabbit) skip() {
	fmt.Println("小白兔,跳来跳去真可爱")
}

// 一个结构体实现多个接口,其实跟一个一个的实现接口是一样的

type Ainterface interface {
	getinfo() string
}

type Binterface interface {
	setinfo(string, int)
}

type People struct {
	Name string
	Age  int
}

func (p People) getinfo() string {
	return fmt.Sprintf("姓名:%v 年龄:%d", p.Name, p.Age)
}

func (p *People) setinfo(name string, age int) {
	p.Name = name
	p.Age = age
}

// 接口嵌套, 接口与接口之间可以通过嵌套创造出新的接口。

type Sayinterface interface {
	say()
}

type Moveinterface interface {
	move()
}

// 接口嵌套

type AnimalCat interface {
	Sayinterface
	Moveinterface
}

type Cat struct {
	name string
}

func (c Cat) say() {
	fmt.Println("小猫~~喵喵喵~~~")
}

func (c Cat) move() {
	fmt.Println("小猫咪会动哦!")
}

func main() {
	/*
		2.接口的定义
			接口是一套标准,定义了对象的行为规范。只定义规范不实现。
			通俗的讲接口就一个标准,它是对一个对象的行为和规范进行约定,约定实现接口的对象必须得按照接口的规范。
			Golang中接口interface是一组方法method的集合。
			Golang中的接口也是一种数据类型。
			Golang接口的定义格式是:
				type 接口名称 interface{
					方法名1(参数列表1) 返回值列表1
					方法名2(参数列表2) 返回值列表2
					......
				}
			其中:参数列表和返回值列表可以省略。
	*/
	// 实例1:定义一个Usber接口让Phone和Camera结构体实现这个接口
	phone1 := Phone{
		Name: "小米",
	}
	var p Usber = phone1 // phone 实现了Usb接口
	p.Start()            // 小米 开始工作
	p.Stop()             // 手机 停止工作

	camera1 := Camera{}
	var c Usber = camera1 // camera 实现了Usb接口
	c.Start()             // 相机开始工作
	c.Stop()              // 相机停止工作

	// 实例2:Computer 结构体中的Work方法必须传入一个Usb的接口
	println()
	phone2 := Phone{
		Name: "华为手机",
	}
	camera2 := Camera{}
	computer := Computer{}
	// 把手机插入电脑的Usb接口开始工作
	computer.Work(phone2)
	// 把相机插入电脑的Usb接口开始工作
	computer.Work(camera2)
	/*	实例2的代码执行打印结果如下:
		华为手机 开始工作
		手机 停止工作
		相机开始工作
		相机停止工作
	*/

	// 3.空接口,可以表示任意类型

	// 查看变量的类型
	println()
	var x interface{}
	s := "golang"
	x = s
	fmt.Println(x)
	fmt.Printf("type:%T, value:%v \n", x, x)

	// 3.1 空接口作为函数的参数
	show(20)             // 值:20  类型:int
	show("你好, golang") // 值:你好, golang  类型:string
	show(true)           // 值:true  类型:bool
	slic := []int{1, 2, 3, 4}
	show(slic) // 值:[1 2 3 4]  类型:[]int

	// 3.2map的值实现空接口
	var stuInfos = make(map[interface{}]interface{})
	stuInfos[28] = "xiaoming"
	stuInfos["Class"] = "三年级"
	stuInfos["age"] = 10
	stuInfos[true] = 1
	stuInfos["wife"] = []string{"潘金莲", "范冰冰", "唐嫣"}
	fmt.Println(stuInfos) // map[true:1 28:xiaoming Class:三年级 age:10 wife:[潘金莲 范冰冰 唐嫣]]

	var studentInfo = make(map[string]interface{})
	studentInfo["name"] = "张三"
	studentInfo["age"] = 18
	studentInfo["married"] = false
	fmt.Println(studentInfo) // map[age:18 married:false name:张三]

	// 3.3定义空接口类型的切片
	//var slice = []interface{}{"李四", 20, true, 32.2}
	var slice = []interface{}{"李四", 20, true, 32.2}
	fmt.Printf("type=%T , value=%v \n", slice, slice) // type=[]interface{}, value=[李四 20 true 32.2]
	fmt.Println(slice)                                // [李四 20 true 32.2]

	// 4. 类型断言
	// 4.1 一 类型断言; 变量x.(T) ,x表示一个变量,T表示断言x变量可能是某Type类型。返回值是两个,一个value值,一个布尔值
	var m interface{}
	m = "hello golang world"
	v, ok := m.(string) // 判断m变量的类型是string
	if ok {
		fmt.Println(v) // 打印输出 hello golang world
	} else {
		fmt.Println("类型断言失败")
	}
	// 4.2 二 注意: 变量.(type)语法只能结合switch语句使用。
	justifyType("lisanduo")

	// 5.结构体值接收者和指针接收者实现接口的区别
	println()
	// 5.1 值接收者
	fan := Fan{
		Name: "霸王风扇",
	}
	var f UsbValue = fan
	f.start() // 霸王风扇 开始工作
	f.stop()  // 风扇 停止工作

	// 5.2 指针接收者
	println()
	Ra := Rabbit{
		Name: "小白兔",
	}
	var up UsbPointer = &Ra
	up.run()  // 小白兔 真可爱,跑起来
	up.skip() // 小白兔,跳来跳去真可爱

	// 6.一个结构体实现多个接口
	println()
	var people = &People{
		Name: "张三",
		Age:  20,
	}

	// people 实现了Ainterface和Binterface接口
	var p1 Ainterface = people
	var p2 Binterface = people

	fmt.Println(p1.getinfo()) // 姓名:张三 年龄:20
	p2.setinfo("李四", 30)
	fmt.Println(p1.getinfo()) // 姓名:李四 年龄:30

	// 7.接口嵌套	,接口与接口之间可以通过嵌套创造出新的接口
	println()
	var Anica AnimalCat = Cat{
		name: "花花",
	}
	Anica.move() // 小猫咪会动哦!
	Anica.say()  // 小猫~~喵喵喵~~~

	println()

	/*	以上代码的全部执行结果如下:
		PS C:\Users\Zhaoshan.lu\go\DaDi> go run .\23.go
		小米 开始工作
		手机 停止工作
		相机开始工作
		相机停止工作

		华为手机 开始工作
		手机 停止工作
		相机开始工作
		相机停止工作

		golang
		type:string, value:golang
		值:20  类型:int

		霸王风扇 开始工作
		风扇 停止工作

		小白兔 真可爱,跑起来
		小白兔,跳来跳去真可爱

		姓名:张三 年龄:20
		姓名:李四 年龄:30

		小猫咪会动哦!
		小猫~~喵喵喵~~~

	*/

}

/*
	因为空接口可以存储任意类型值的特点,所以空接口在Go语言中的使用十分广泛。
	关于接口需要注意的是:只有当有两个或两个以上的具体类型必须以相同的方式进行处理时才需要定义接口。不要为了接口而写接口,
	那样只会增加不必要的抽象,导致不必要的运行时损耗。
*/

func justifyType(x interface{}) {
	// 注意: 变量.(type)语法只能结合switch语句使用。
	switch v := x.(type) {
	case string:
		fmt.Printf("x is a string, value is %v \n", v) // main()函数中调用justifyType()函数后,此处会被打印输出
	case int:
		fmt.Printf("x is a int, value is %v \n", v)
	case bool:
		fmt.Printf("x is a bool, value is %v \n", v)
	default:
		fmt.Println("unsupport type! ")
	}

}



posted @ 2022-12-29 17:30  大海一个人听  阅读(84)  评论(0编辑  收藏  举报