# 11.4 类型判断:type-switch

接口变量的类型也可以使用一种特殊形式的 switch 来检测:type-switch (下面是示例 11.4 的第二部分):

  1. switch t := areaIntf.(type) {
  2. case *Square:
  3. fmt.Printf("Type Square %T with value %v\n", t, t)
  4. case *Circle:
  5. fmt.Printf("Type Circle %T with value %v\n", t, t)
  6. case nil:
  7. fmt.Printf("nil value: nothing to check?\n")
  8. default:
  9. fmt.Printf("Unexpected type %T\n", t)
  10. }

输出:

  1. Type Square *main.Square with value &{5}

变量 t 得到了 areaIntf 的值和类型, 所有 case 语句中列举的类型(nil 除外)都必须实现对应的接口(在上例中即 Shaper),如果被检测类型没有在 case 语句列举的类型中,就会执行 default 语句。

可以用 type-switch 进行运行时类型分析,但是在 type-switch 不允许有 fallthrough

如果仅仅是测试变量的类型,不用它的值,那么就可以不需要赋值语句,比如:

  1. switch areaIntf.(type) {
  2. case *Square:
  3. // TODO
  4. case *Circle:
  5. // TODO
  6. ...
  7. default:
  8. // TODO
  9. }

下面的代码片段展示了一个类型分类函数,它有一个可变长度参数,可以是任意类型的数组,它会根据数组元素的实际类型执行不同的动作:

  1. func classifier(items ...interface{}) {
  2. for i, x := range items {
  3. switch x.(type) {
  4. case bool:
  5. fmt.Printf("Param #%d is a bool\n", i)
  6. case float64:
  7. fmt.Printf("Param #%d is a float64\n", i)
  8. case int, int64:
  9. fmt.Printf("Param #%d is a int\n", i)
  10. case nil:
  11. fmt.Printf("Param #%d is a nil\n", i)
  12. case string:
  13. fmt.Printf("Param #%d is a string\n", i)
  14. default:
  15. fmt.Printf("Param #%d is unknown\n", i)
  16. }
  17. }
  18. }

可以这样调用此方法:classifier(13, -14.3, "BELGIUM", complex(1, 2), nil, false)

在处理来自于外部的、类型未知的数据时,比如解析诸如 JSON 或 XML 编码的数据,类型测试和转换会非常有用。

在示例 12.17(xml.go)中解析 XML 文档时,我们就会用到 type-switch

练习 11.4 simple_interface2.go:

接着练习 11.1 中的内容,创建第二个类型 RSimple,它也实现了接口 Simpler,写一个函数 fi,使它可以区分 SimpleRSimple 类型的变量。

链接