0
点赞
收藏
分享

微信扫一扫

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 语法


举报

相关推荐

0 条评论