leisore 10 лет назад
Родитель
Сommit
71ff6140c5
3 измененных файлов с 81 добавлено и 4 удалено
  1. 3 3
      eBook/11.3.md
  2. 76 0
      eBook/11.4.md
  3. 2 1
      eBook/directory.md

+ 3 - 3
eBook/11.3.md

@@ -1,4 +1,4 @@
-# 11.3 如何检测和转换接口变量的类型:类型断言
+# 11.3 类型断言:如何检测和转换接口变量的类型
 
 一个接口类型的变量 `varI` 中可以包含任何类型的值,必须有一种方式来检测它的 **动态** 类型,即运行时在变量中存储的值的实际类型。在执行过程中动态类型可能会有所不同,但是它总是可以分配给接口变量本身的类型。通常我们可以使用 **类型断言** 来测试在某个时刻 `varI` 是否包含类型 `T` 的值:
 
@@ -89,8 +89,8 @@ func (ci *Circle) Area() float32 {
 
 **备注**
 
-如果忽略 `areaIntf.(*Square)` 中的 `*` 号,会导致编译错误:`impossible type assertion: Square does not implement Shaper (Area method has pointer receiver)`
+如果忽略 `areaIntf.(*Square)` 中的 `*` 号,会导致编译错误:`impossible type assertion: Square does not implement Shaper (Area method has pointer receiver)`
 
 - [目录](directory.md)
 - 上一章:[11.2 接口嵌套接口](11.2.md)
-- 下一节:[11.4 类型switch](11.4.md)
+- 下一节:[11.4 类型判断:type-switch](11.4.md)

+ 76 - 0
eBook/11.4.md

@@ -0,0 +1,76 @@
+# 11.3 类型判断:type-switch
+
+接口变量的类型也可以使用一种特殊形式的 `swtich` 来检测:**type-swtich** (下面是 示例 11.4 的第二部分):
+
+```go
+	switch t := areaIntf.(type) {
+	case *Square:
+		fmt.Printf("Type Square %T with value %v\n", t, t)
+	case *Circle:
+		fmt.Printf("Type Circle %T with value %v\n", t, t)
+	case nil:
+		fmt.Printf("nil value: nothing to check?\n")
+	default:
+		fmt.Printf("Unexpected type %T\n", t)
+	}
+```
+
+输出:
+
+    Type Square *main.Square with value &{5}
+
+变量 `t` 得到了 `areaIntf` 的值和类型, 所有 `case` 语句中列举的类型(`nil` 除外)都必须实现对应的接口(在上例中即 `Shaper`),如果被检测类型没有在 `case` 语句列举的类型中,就会执行`default` 语句。
+
+可以用 `type-switch` 进行运行时类型分析,但是在 `type-switch` 不允许有 `fallthrough` 。
+
+如果仅仅是测试变量的类型,不用它的值,那么就可以不需要赋值语句,比如:
+
+```go
+	switch areaIntf.(type) {
+	case *Square:
+		// TODO
+	case *Circle:
+		// TODO
+	...
+	default:
+		// TODO
+	}
+```
+
+下面的代码片段展示了一个类型分类函数,它有一个可变长度参数,可以是任意类型的数组,它会根据数组元素的实际类型执行不同的动作:
+
+```go
+
+func classifier(items ...interface{}) {
+	for i, x := range items {
+		switch x.(type) {
+		case bool:
+			fmt.Printf("Param #%d is a bool\n", i)
+		case float64:
+			fmt.Printf("Param #%d is a float64\n", i)
+		case int, int64:
+			fmt.Printf("Param #%d is a int\n", i)
+		case nil:
+			fmt.Printf("Param #%d is a nil\n", i)
+		case string:
+			fmt.Printf("Param #%d is a string\n", i)
+		default:
+			fmt.Printf("Param #%d is unknown\n", i)
+		}
+	}
+}
+```
+
+可以这样调用此方法:`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`,它可以区分 `Simple` 和 `RSimple` 类型的变量。
+
+- [目录](directory.md)
+- 上一章:[11.3 类型断言:如何检测和转换接口变量的类型](11.3.md)
+- 下一节:[11.5 测试一个值是否实现了某个接口](11.5.md)

+ 2 - 1
eBook/directory.md

@@ -96,7 +96,8 @@
 - 第11章:[接口(interface)与反射(reflection)](11.0.md)
     - 11.1 [接口是什么](11.1.md)
     - 11.2 [接口嵌套接口](11.2.md)
-    - 11.3 [11.3 如何检测和转换接口变量的类型:类型断言](11.3.md)
+    - 11.3 [类型断言:如何检测和转换接口变量的类型](11.3.md)
+    - 11.4 [类型判断:type-switch](11.4.md)
 
 ## 第三部分:Go 高级编程