Golang 的 interface{} 的用法

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]
}

本文由 上传。


如果您喜欢这篇文章,请点击链接 Golang 的 interface{} 的用法 查看原文。


您也可以直接访问:https://www.fanfine.cn/blog/108

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇