什么是接口
- 即:将一些共性方法集合在一起
- 方法的集合,不需要方法的具体内容
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类型")
}
}