什么是接口
- 即:将一些共性方法集合在一起
- 方法的集合,不需要方法的具体内容
package mainimport "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 USBusb = mouse// 只能调用usb接口中的方法,不能调用 mouse 结构体中的属性// usb.name // usb.name undefined (type USB has no field or method name)usb.input()}
go 空接口
- 所有结构体都实现类空接口个,空接口可以存储任何类型
- interface {} == any
package mainimport "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 {} == anyvar 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 = 1fmt.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"] = a1map1["a2"] = a2map1["a3"] = a3fmt.Println(map1) // map[a1:{小鸡毛} a2:1 a3:string]}
接口类型
package mainimport "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 := anyany3 := anyfmt.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 mainimport "fmt"type AA interface {test1()
}type BB interface {test2()
}// 定义接口CC : 如果实现CC接口,需要实现test1()/test2()/test3() 三个方法
type CC interface {// 嵌套 接口AA // 导入AA接口中的方法BBtest3()
}// 编写一个结构体 , 实现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 mainimport "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类型")}
}