第二十八回:Go 类型断言 (Type Assertion)

唐伯虎点秋香大结局
华夫人
华夫人: 这里的二十个新娘都盖着红盖头(空接口 interface{}),看起来都一样。唐伯虎,你若能点中秋香,我就把她许配给你!
唐伯虎
唐伯虎: 这有何难?待我用类型断言神功,掀起她们的盖头来!

🔍 揭开盖头 (Type Assertion)

当我们手里拿着一个接口类型的变量(比如 anyinterface{}),我们想知道它里面到底藏着什么具体的类型,就需要断言。

语法: value, ok := interfaceValue.(TargetType)

package main
import "fmt"

type Qiuxiang struct {
    Name string
}

type Shiliu struct {
    Face string
}

func main() {
    // 华夫人给了一个新娘(用空接口包装)
    var bride interface{} = Qiuxiang{Name: "秋香"}

    // 唐伯虎尝试断言:这是秋香吗?
    // q: 如果成功,q就是秋香结构体
    // ok: 如果成功,ok为true
    q, ok := bride.(Qiuxiang)

    if ok {
        fmt.Println("终于找到你了!", q.Name)
    } else {
        fmt.Println("哎呀,认错人了!")
    }
}

⚠️ 风险:不加 ok 的豪赌

如果你非常自信,可以省略 ok。但如果猜错了,程序会直接崩溃(Panic)!

石榴姐
石榴姐: 竟然敢不确认就直接亲?老娘吓死你!(Panic)
唐伯虎
唐伯虎: 哎呀!我的小心脏!如果不加 ok 判断,一旦断言失败,整个程序直接挂掉,我也得吐血三升!
var bride interface{} = Shiliu{Face: "绝世容颜"}

// ❌ 危险操作:强制断言是秋香
// q := bride.(Qiuxiang) 
// 报错:panic: interface conversion: interface {} is main.Shiliu, not main.Qiuxiang

🔀 类型选择 (Type Switch):批量筛选

如果有很多人,我想一次性判断她们是谁,可以用 switch

func Identify(person interface{}) {
    // switch 配合 .(type) 关键字
    switch v := person.(type) {
    case Qiuxiang:
        fmt.Println("哇!是秋香!", v.Name)
    case Shiliu:
        fmt.Println("呃... 是石榴姐。", v.Face)
    case string:
        fmt.Println("这只是个名字:", v)
    case int:
        fmt.Println("这是个编号:", v)
    default:
        fmt.Println("不认识的类型")
    }
}

🎯 练功房(真假新娘)

判断变量 v 到底是什么类型。

package main
import "fmt"

func check(v any) {
    // 填空:类型选择语法
    switch val := v.(______) {
    case int:
        fmt.Println("是整数:", val)
    case string:
        fmt.Println("是字符串:", val)
    }
}

func main() {
    check(100)
    check("秋香")
}

任务: 填补空白处的关键字。

答案: type

解析: v.(type) 是固定写法,只能用在 switch 语句中。