golang语言 接口

接口值由动态类型和动态值组成

未初始化的接口类型变量的值为nil,其动态类型和动态值都是nil,调用nil接口值上的方法会产生panic

所有类型都实现了空接口interface{},任意值都能赋给空接口类型

接口里方法的名字必须是唯一的,名字相同,参数或返回值不同,也会报错

接口可以内嵌其他接口,这被称为嵌入接口,不能直接或间接的嵌入自己

Go1.14开始,相同的方法可以被重复嵌入

接收者为指针*T的方法,虽然能用T类型的值去调用,但这只是语法糖,T的方法集里没有该方法,所以T没有实现对应的接口

 

接口类型 Y 有m方法,编译器会隐式声明一个对应的函数 Y.m,第一个参数的类型为 Y

对于 Y 类型的值 y ,y.m(..) 等价于 Y.m( y, .. )

 

    可以把一个接口类型的变量a赋值给另一个接口类型的变量b,只要a包含b的所有方法
    var w io.Writer
    var rwc io.ReadWriteCloser
    w = rwc     // OK: io.ReadWriteCloser has Write method
    rwc = w     // compile error: io.Writer lacks Close method
    // 即使w的动态类型实现了read write close三个方法也不行

    接口类型封装和隐藏具体类型和它的值。即使具体类型有其它的方法也只有接口的方法能被调用:
    os.Stdout.Write([]byte("hello"))     // OK: *os.File has Write method
    os.Stdout.Close()                 // OK: *os.File has Close method
    var w io.Writer
    w = os.Stdout                    // 等价于    w = io.Writer(os.Stdout)
    w.Write([]byte("hello"))             // OK: io.Writer has Write method
    w.Close()                     // compile error: io.Writer lacks Close method

 

 

类型断言 x.(T)

1,T是具体类型,断言的作用是检查x的动态类型是不是T,若是T,返回T类型的动态值,即返回接口x里的具体值,若不是T,则抛出panic

2,T是接口类型,断言的作用是检查x的动态类型是否实现了T接口,若实现了T,返回值是T类型的接口值,其动态类型以及动态值和x一样,方法集有所改变。失败会panic

 

如果赋值给两个变量,例如 f, ok := x.(T),在断言失败时不会抛出panic,f是T类型的零值,ok是false

如果x是nil接口值,那么断言总是失败的

 

类型选择  switch x.(type)

x 必须为接口类型 而每一个在case中列出的非接口类型 T 必须实现了 x 接口。

类型选择监视可包含一个短变量声明 当使用此形式时,变量会在每个子句的隐式块的起始处声明。 在case列表只有一个类型的子句中,该变量即拥有此类型;否则,该变量拥有x的类型。

case中的类型可为 nil, 这种情况在类型选择监视中的表达式为 nil 接口值时使用。

类型选择中不能使用fallthrough语句,没有case相当于空操作

 

    switch i := x.(type) {            // 也可写为 x := x.(type),或者直接 x.(type)
    case nil:
        printString("x is nil")                // i 的类型为 x 的类型(interface{})
    case int:
        printInt(i)                            // i 的类型为 int
    case float64:
        printFloat64(i)                        // i 的类型为 float64
    case func(int) float64:
        printFunction(i)                       // i 的类型为 func(int) float64
    case bool, string:
        printString("type is bool or string")  // i 的类型为 x 的类型(interface{})
    default:
        printString("don't know the type")     // i 的类型为 x 的类型(interface{})
    }


    可被重写为:
    v := x  // x 只被求值一次
    if v == nil {
        i := v                                 // i 的类型为 x 的类型(interface{})
        printString("x is nil")
    } else if i, isInt := v.(int); isInt {
        printInt(i)                            // i 的类型为 int
    } else if i, isFloat64 := v.(float64); isFloat64 {
        printFloat64(i)                        // i 的类型为 float64
    } else if i, isFunc := v.(func(int) float64); isFunc {
        printFunction(i)                       // i 的类型为 func(int) float64
    } else {
        _, isBool := v.(bool)
        _, isString := v.(string)
        if isBool || isString {
            i := v                         // i 的类型为 x 的类型(interface{})
            printString("type is bool or string")
        } else {
            i := v                         // i 的类型为 x 的类型(interface{})
            printString("don't know the type")
        }
    }

 

 

    type P struct { }
    func (p P) add() int { return 1 }
    type T interface { add() int }

    m := map[int]int(nil)
    fmt.Printf("%T\n",m)       // map[int]int

    t := T(nil)
    fmt.Printf("%T\n",t)           // nil
    tt, ok := t.(T)                    // nil  false

    var p P
    t = p
    fmt.Printf("%T\n",t)           // P

 

posted @ 2020-05-27 20:45  是的哟  阅读(164)  评论(0编辑  收藏  举报