061-类型开关(Type Switch)

这一篇仍然是与类型断言相关的,只是稍微再延伸一下。没事,不要怕,没你想象的复杂。

到目前为止,关于接口我们已经掌握了它的两种使用方法:

  • 实现了同一个接口的不同具体类型都具有共性特征,而接口屏蔽了底层细节。此时我们的关注的是接口的『方法』,而不是类型。
  • 使用类型断言,我们可以判断接口值的类型。此时我们关注的是接口的『类型』和『值』,而不是方法。

第二种方法通常被描述为 discriminated unions,它在计算机英语里是常见的术语,不知道怎么翻译。简单的说,接口是一种存放对象和对象所属类型标记的一种数据结构,即 discriminated unions,你可以叫它『标识联合』、『可辨识联合』随你了。

1. 类型开关(Type Switch)

通常我们可能会有一连串的 if … else 结构来判断接口类型,以便于做出不同的决策:

var e interface{}
// e = ... 

if e == nil {
    // ...
} else if v, ok := e.(int); ok {
    // ...
} else if v, ok := e.(float32); ok {
    // ...
} else if v, ok := e.(string); ok {
    // ...
} else if v, ok := e.(bool); ok {
    // ...
}

如果每次都这样写,相当费劲。Golang 关键字 swtich 支持一种非常便捷的写法,你可以这样:

var e interface{}
// e = ... 

switch v := e.(type) {
case nil:
    // ...
case int, uint, int32, uint32:
    // ...
case string:
    // ...
case bool:
    // ...
default:
    // ...
}

注意上面的语法:e.(type) 只能用在 switch 关键字后面,它会返回 e 接口中的值部分。当然你可以完全忽略 e.(type) 返回的值:

switch e.(type) {
case nil:
// ...
}

下面是一个非常简单的例子:

package main

import (
    "fmt"
    "io"
    "os"
)

func show(e interface{}) {
    switch v := e.(type) {
    case nil:
        fmt.Printf("Don't input nil\n")
    case int, uint, int32, uint32, float32, float64:
        fmt.Printf("This is a number: %v\n", v)
    case string:
        fmt.Printf("This is a string: %s\n", v)
    case bool:
        fmt.Printf("This is a boolean: %v\n", v)
    case io.Writer:
        fmt.Printf("This is a writer: %T\n", v)
    case *os.File:
        fmt.Printf("This is a *os.File\n")
    default:
        fmt.Printf("I don't know what it is\n")
    }
}

func main() {
    show(5)                     // This is a number: 5
    show("hello world")         // This is a string: hello world
    show(true)                  // This is a boolean: true
    show(5.6)                   // This is a number: 5.6
    show(os.Stdout)             // This is a writer: *os.File
    show([]int{1 2 3 4})   // I don't know what it is
}

上面需要特别注意的是,case 后面你可以断言 e.(type) 是某种接口类型,就像 case io.Writer 一样。

尽管 os.Stdout*os.File 类型,但是由于 case io.Writer 写在 case *os.File 前面,所以 case *os.File 后面的语句就不会执行了。

2. 总结

  • 掌握 type switch 语法

猜你喜欢

转载自blog.csdn.net/q1007729991/article/details/80717657