Go 类型断言 ( type assertion )

Go 类型断言 ( type assertion )


Go里的所有类型都实现了空接口interface{},所以通常将它作为一个传参变量或者结构体的字段,以实现对类型的抽象。我们知道,Go的interface变量包含两个东西,一个是类型,一个是值。为了判断接口所绑定的类型,Go提供类型断言,type assertion这个方法。

基本语法

一个类型断言检查一个接口对象x的动态类型是否和断言的类型T匹配

x.(T) // 判断x的类型是否是T,其中x必须是接口值。

t := x.(T) // 不安全的type assertion,如果断言失败,会报panic

t,ok : = x.(T) // 安全的type assertion,即使断言失败,也可以根据ok值来做处理,而不会出现panic

应用场景

两个类型实现了Read接口,都是读,只不过读的地方不一样

type R interface{
    Read()
} 

type ReadFromFile struct{}

func (r *ReadFromFile) Read() {
    fmt.Println("read from file")
}

type ReadFromDisk struct{}

func (r *ReadFromDisk) Read() {
    fmt.Println("read from disk")
}

· 函数以接口类型当参数

通常检查r这个d动态类型是否满足switch case中的类型。如果检查成功,则检查结果的接口值的动态类型和动态值不变,但是该接口值的类型被转换为接口类型T。一般情况下,和switch case搭配使用。

func ReadSomething(r *R) {
    switch t := r.(type) {
    case *ReadFromFile :
        fmt.Println("this is read from file",r.read())
    case *ReadFromDisk :
        fmt.Println("this is read from disk",r.read())
    default:
        fmt.Println("wrong type")
        return
    }
}

· 检查具体类型

具体类型则检查是接口类型是否为T。如果检查成功,类型断言的结果是一个类型为T的对象,该对象的值为接口变量x的值,即下面的reader的值。

func main() {
    var reader  R
    reader = &ReadFromDisk{}
    t,ok := reader.(*ReadFromDisk)
    if !ok {
        panice("not *ReadFromDisk type")
    }
    
    fmt.Println("t : %T",t)
}

你可能感兴趣的:(Go)