Go语言接口interface的用法
interface{} 是 Go 语言中的空接口,它可以存储任何类型的值。以下是 interface{} 的一些基本用法和应用场景。
断言
// 测试断言
func TestInterfaceAssert(t *testing.T) {
// 1. 断言的正确用法
var name interface{} = "Fan的小破站"
// 使用断言的方式获取值,
theName := name.(string)
fmt.Println(theName)
// 2. 断言的错误用法
// var age interface{} = 1
// panic: interface conversion: interface {} is int, not string
// theAge := age.(string)
// fmt.Println(theAge)
// 3. 使用断言判断类型
var ok interface{} = Cat{"小猫"}
switch ok.(type) {
case bool:
fmt.Println("ok 是 bool 类型")
case string:
fmt.Println("ok 是 string 类型")
case Cat:
fmt.Println("ok 是 Cat 类型")
default:
fmt.Println("ok 是其他类型")
}
// 4. 断言判断类型的具体场景
defer func() {
// recover()会得到panic的参数
r := recover()
switch r.(type) {
case error:
fmt.Println("recover 是 error 类型")
case Cat:
fmt.Println("recover 是 Cat 类型")
default:
fmt.Println("recover 是其他类型")
}
}()
// panic(fmt.Errorf("panic了")) // panic一个error类型
panic(Cat{"小黑"}) // panic一个 自定义类型
fmt.Println("panic 之后的打印,不会发生")
}
接口实现
// 动物接口
type Animal interface {
Run() // run 方法
}
// 猫
type Cat struct {
Ctx context.Context
Name string `json:"name"`
}
// 猫猫工厂函数
func NewCatSys(ctx context.Context) *Cat {
return &Cat{
Ctx: ctx,
}
}
// 猫实现Run的方法,此时就实现了Animal接口
// (若Animal中增加了方法,则Cat需要实现该方法)
func (cat *Cat) Run() {
fmt.Println("猫在跑")
}
// 狗
type Dog struct {
Ctx context.Context
Name string `json:"name"`
}
// 狗子工厂函数
func NewDogSys(ctx context.Context) *Dog {
return &Dog{
Ctx: ctx,
}
}
// 狗实现Run的方法,此时就实现了Animal接口
// (若Animal中增加了方法,则Cat需要实现该方法)
func (dog *Dog) Run() {
fmt.Println("狗在跑")
}
// 动物工厂函数
func NewAnimal(ctx context.Context, who string) Animal {
switch who {
case "cat":
return NewCatSys(ctx)
case "dog":
return NewDogSys(ctx)
default:
panic(errors.New("不支持的动物"))
}
}
// 测试接口实现
func TestInterface(t *testing.T) {
defer func() {
if err := recover(); err != nil {
fmt.Println("err:", err)
}
}()
ctx := context.Background()
animal := NewAnimal(ctx, "cat")
animal.Run() // 猫在跑
animal = NewAnimal(ctx, "dog")
animal.Run() // 狗在跑
animal = NewAnimal(ctx, "duck") // 不支持的动物
animal.Run()
}
接口继承
// 宠物接口,继承了Animal
type Pet interface {
Animal
Speak()
}
func (cat *Cat) Speak() {
fmt.Println("喵喵喵!猫在叫")
}
func TestInterfaceInherit(t *testing.T) {
pet_cat := NewCatSys(context.Background())
pet_cat.Speak() // 喵喵喵!猫在叫
pet_cat.Run() // 猫在跑
pet := NewDogSys(context.Background())
// pet.Speak() // 狗类型未能实现Speak方法,所以会报错
pet.Run() // 狗在跑
}
反射 (reflect)
// 测试反射
func TestReflection(t *testing.T) {
var value interface{} = "Fan的小破站"
fmt.Println(reflect.TypeOf(value)) // 获取类型 string
fmt.Println(reflect.ValueOf(value)) // 获取值 Fan的小破站
}
空接口作为函数参数
当函数需要接受任何类型的参数时,可以使用 interface{} 类型。这使得函数具有很高的通用性。
// 空接口作为参数
func printValue(v interface{}) {
fmt.Println(v)
}
// 定义一个函数类型
type funcVar func(domain string) string
// v也可以传递函数
func doHandler(v interface{}) {
switch v.(type) {
case func(string) string:
result := v.(func(string) string)("fanfine.cn")
fmt.Println(result)
// 或
handler := v.(func(string) string)
result = handler("www.fanfine.cn")
fmt.Println(result)
case funcVar:
result := v.(funcVar)("fanfine.cn")
fmt.Println(result)
// 或
handler := v.(funcVar)
result = handler("www.fanfine.cn")
fmt.Println(result)
}
}
// 空接口作为函数参数
func TestEmptyInterface(t *testing.T) {
// 传入具体参数
printValue("Fan的小破站")
printValue(1)
printValue(true)
printValue([]int{1, 2, 3})
printValue(map[string]int{"a": 1, "b": 2})
// 传入函数
doHandler(
func(domain string) string {
return domain
})
// 或传入已知类型函数
var handler funcVar = func(domain string) string {
return domain
}
doHandler(handler)
}
延迟绑定(Late Binding)
运行时才决定具体行为,使用场景:插件、多态等
// 延迟绑定
type Operation func(int, int) int
func performOperation(op Operation, a, b int) int {
return op(a, b)
}
func add(a, b int) int { return a + b }
func subtract(a, b int) int { return a - b }
func TestLateBinding(t *testing.T) {
var operation Operation
// 使用add函数
operation = add
result := performOperation(operation, 10, 5)
fmt.Println("Result:", result) // 15
// 使用subtract函数
operation = subtract
result = performOperation(operation, 10, 5)
fmt.Println("Result:", result) // 5
// 多态
cat := &Cat{}
dog := &Dog{}
animalRun([]Animal{cat, dog}) // 猫在跑 狗在跑
}
// animalRun 函数接收一个 Animal 接口类型的切片
func animalRun(animals []Animal) {
for _, animal := range animals {
animal.Run()
}
}
映射 & 列表等
// 测试interface{}作为key,v的map,slice的value
func TestInterfaceMapSlice(t *testing.T) {
var data = map[interface{}]interface{}{
"domain": "fanfine.cn",
"name": "Fan的小破站",
"age": 1,
123: "123",
}
fmt.Println(data) // map[123:123 age:1 domain:fanfine.cn name:Fan的小破站]
list := []interface{}{
"domain",
"name",
"age",
123,
}
fmt.Println(list) // [domain name age 123]
}


