day09 接口

什么是接口

  • 即:将一些共性方法集合在一起
  • 方法的集合,不需要方法的具体内容
package main

import "fmt"

// 定义接口 使用 interface. 结合 struct 结构体使用
type USB interface {
	input()  // 输入 方法
	output() // 输出 方法
}
type Mouse struct {
	name string
}

type KeyBord struct {
	name string
}

// 实现 接口的全部方法,就代表实现类这个接口
func (m Mouse) input() {
	fmt.Println(m.name, "鼠标输入")

}
func (m Mouse) output() {
	fmt.Println(m.name, "鼠标输出")

}
func (k KeyBord) input() {
	fmt.Println(k.name, "键盘输入")

}
func (k KeyBord) output() {
	fmt.Println(k.name, "键盘输入")

}

func realizeUsb(usb USB) {
	usb.input()
	usb.output()
}

func main() {
	/*
		go中的接口
			- 什么是接口? 即:将一些共性方法集合在一起
			- 接口是:方法的集合,不需要方法的具体内容
	*/
	// 通过传入`接口` 来实现调用
	mouse := Mouse{name: "罗技"}
	// realizeUsb 的参数 是接口类型,如果一个结构体实现这个接口的所有方法,则结构体就是接口类型
	realizeUsb(mouse)
	keyboard := KeyBord{name: "镭射"}
	realizeUsb(keyboard)

	// 定义高级类型
	var usb USB
	usb = mouse
	// 只能调用usb接口中的方法,不能调用 mouse 结构体中的属性
	// usb.name // usb.name undefined (type USB has no field or method name)
	usb.input()

}

go 空接口

  • 所有结构体都实现类空接口个,空接口可以存储任何类型
  • interface {} == any
package main

import "fmt"

// 定义空接口,实现包容万物
type EmptyInterface interface {
}

type DogEmptyStruct struct {
	name string
}

// 定义空接口实现方法
func emptyInterfaceFunc(ei EmptyInterface) {
	fmt.Printf("空接口实现函数。【参数:%v  ----  类型:%T】\n", ei, ei) // main.DogEmptyStruct
}

// 万能接口. 空接口作为函数的参数// main.DogEmptyStruct
func emptyInterfaceFunc2(universalInterface interface{}) {
	fmt.Printf("万能接口。【参数:%v  ----  类型:%T】\n", universalInterface, universalInterface)

}
func main() {
	/*空接口*/
	// 所有结构体都实现类空接口个,空接口可以存储任何类型
	// interface {} == any

	var dogEmpty = DogEmptyStruct{name: "小鸡毛"}
	emptyInterfaceFunc(dogEmpty)
	fmt.Println("-----")
	//
	var a1 EmptyInterface = DogEmptyStruct{name: "小鸡毛"}
	fmt.Printf("a1 【参数:%v  ----  类型:%T】\n", a1, a1) // 【参数:{小鸡毛}  ----  类型:main.DogEmptyStruct】

	var a2 EmptyInterface = 1
	fmt.Printf("a2 【参数:%v  ----  类型:%T】\n", a2, a2) // 【参数:1  ----  类型:int】

	var a3 EmptyInterface = "string"
	fmt.Printf("a3 【参数:%v  ----  类型:%T】\n", a3, a3) // 【a3 【参数:string  ----  类型:string】

	fmt.Println(a1, a2, a3)
	fmt.Println("万能参数,空接口-----")
	emptyInterfaceFunc2(1)
	emptyInterfaceFunc2("string")
	emptyInterfaceFunc2(make([]string, 10))

	fmt.Println("空接口对map和slice的使用-----")
	map1 := make(map[string]interface{})
	map2 := make(map[string]any)
	fmt.Printf("map1 【类型:%T】\n", map1) // 【类型:map[string]interface {}】

	fmt.Printf("map2 【类型:%T】\n", map2) // 【类型:map[string]interface {}】

	// 空接口能 接收任何类型的参数
	map1["a1"] = a1
	map1["a2"] = a2
	map1["a3"] = a3
	fmt.Println(map1) // map[a1:{小鸡毛} a2:1 a3:string]

}

接口类型

package main

import "fmt"

type MyStruct struct {
	code int
}

type MyInterface interface {
	myInterfaceFunc()
}

func (msc *MyStruct) myInterfaceFunc() interface{} {
	return interface{}(msc.code)
}
func test(msc MyStruct) {
	ret := msc.myInterfaceFunc()
	fmt.Printf("类型:%T\n", ret)
	fmt.Printf("内存地址:%p\n", &ret)
}

func main() {
	ms1 := MyStruct{code: 1}
	test(ms1)
	ms2 := MyStruct{code: 2}
	test(ms2)

	var any interface{}
	fmt.Printf("any类型:%T\n", any)
	fmt.Printf("any内存地址:%p\n", &any)
	any2 := any
	any3 := any
	fmt.Printf("any2类型:%T\n", any2)
	fmt.Printf("any2内存地址:%p\n", &any2)
	fmt.Printf("any3内存地址:%p\n", &any3)
	any = 42
	// 动态类型断言
	if val, ok := any.(int); ok {
		fmt.Println("Value is an integer:", val)
	} else {
		fmt.Println("Value is not an integer")
	}
}

接口嵌套

package main

import "fmt"

type AA interface {
	test1()
}

type BB interface {
	test2()
}

// 定义接口CC : 如果实现CC接口,需要实现test1()/test2()/test3() 三个方法
type CC interface {
	// 嵌套 接口
	AA // 导入AA接口中的方法
	BB
	test3()
}

// 编写一个结构体 , 实现CC
type Dog7 struct {
}

// 函数+结构体参数+接口中定义的函数名
func (d Dog7) test1() {
	fmt.Println("test1")
}
func (d Dog7) test2() {
	fmt.Println("test2")

}
func (d Dog7) test3() {
	fmt.Println("test3")

}
func main() {
	/* 接口的嵌套 */

	// 结构体实例化对象,调用接口 AA / BB / CC 三个方法
	var dog Dog7 = Dog7{}
	dog.test1()
	dog.test2()
	dog.test3()

	// 因为CC接口嵌套了 AA 和 BB 接口。可以定义 某个变量的类型为接口类型。将结构体对象赋值给 这个变量。这个变量就能实现 test1/test2/test3 三个方法
	var c CC = Dog7{} // 向上转型后只能调用自己的方法
	c.test3()
	c.test2()
	c.test1()
	// 因为CC接口嵌套了 AA 和 BB 接口。可以定义 某个变量的类型为接口类型。将结构体对象赋值给 这个变量。这个变量就能实现 test1/test2/test3 三个方法

	var a AA = Dog7{}
	//a.test3() // 向上转型后只能调用自己的方法
	//a.test2() // 向上转型后只能调用自己的方法
	a.test1()

}

接口断言

  • 定义:检查一个接口的变量是不是符合预期调用/值
  • 被断言的对象必须是接口型。否则会报错
  • 格式: t,ok:=i.(T) 【t:就是i接口是T类型的,i:接口,T:类型】
package main

import "fmt"

func main() {
	/*
		接口断言
			- 定义:检查一个接口的变量是不是符合预期调用/值
			- 被断言的对象必须是接口型。否则会报错
			- 格式: t,ok:=i.(T) 【t:就是i接口是T类型的,i:接口,T:类型】
	*/

	assertString("123") // 断言成功,则无异常
	//assertString(123)   // 断言失败就会抛出异常,停止程序【panic: interface conversion: interface {} is int, not string 】
	assertInt("1")
	assertInt(true)
	assertInt(1)
}

// 判断一个变量是不是字符串类型
func assertString(i interface{}) {
	s := i.(string)
	fmt.Println(s)
}

// 断言失败不希望程序停止
func assertInt(i any) {
	i, ok := i.(int)
	fmt.Println(i, ok)
	if ok {
		fmt.Println("int类型")
	} else {
		fmt.Println("非int类型")
	}
}

posted @ 2024-07-02 01:18  染指未来  阅读(3)  评论(0编辑  收藏  举报