leisore 10 年 前
コミット
eaa4c89ef0
3 ファイル変更94 行追加1 行削除
  1. 1 1
      eBook/11.5.md
  2. 92 0
      eBook/11.6.md
  3. 1 0
      eBook/directory.md

+ 1 - 1
eBook/11.5.md

@@ -26,4 +26,4 @@ if sv, ok := v.(Stringer); ok {
 
 
 - [目录](directory.md)
 - [目录](directory.md)
 - 上一章:[11.4 类型判断:type-switch](11.4.md)
 - 上一章:[11.4 类型判断:type-switch](11.4.md)
-- 下一节:[11.6 TODO](11.6.md)
+- 下一节:[11.6 使用方法集与接口](11.6.md)

+ 92 - 0
eBook/11.6.md

@@ -0,0 +1,92 @@
+# 11.6 使用方法集与接口
+
+在 10.6.3 及例子 methodset1.go 中我们看到,作用于变量上的方法实际上是不区分变量到底是指针还是值的。当碰到接口类型值时,这会变得有点复杂,原因是接口变量中存储的具体值是不可寻址的,幸运的是,如果使用不当编译器会给出错误。考虑下面的程序:
+
+示例 11.5 methodset2.go:
+
+```go
+package main
+
+import (
+	"fmt"
+)
+
+type List []int
+
+func (l List) Len() int {
+	return len(l)
+}
+
+func (l *List) Append(val int) {
+	*l = append(*l, val)
+}
+
+type Appender interface {
+	Append(int)
+}
+
+func CountInto(a Appender, start, end int) {
+	for i := start; i <= end; i++ {
+		a.Append(i)
+	}
+}
+
+type Lener interface {
+	Len() int
+}
+
+func LongEnough(l Lener) bool {
+	return l.Len()*10 > 42
+}
+
+func main() {
+	// A bare value
+	var lst List
+	// compiler error:
+	// cannot use lst (type List) as type Appender in argument to CountInto:
+	//       List does not implement Appender (Append method has pointer receiver)
+	// CountInto(lst, 1, 10)
+	if LongEnough(lst) { // VALID:Identical receiver type
+		fmt.Printf("- lst is long enough\n")
+	}
+
+	// A pointer value
+	plst := new(List)
+	CountInto(plst, 1, 10) //VALID:Identical receiver type
+	if LongEnough(plst) {
+		// VALID: a *List can be dereferenced for the receiver
+		fmt.Printf("- plst is long enough\n")
+	}
+}
+```
+
+**讨论**
+
+在 `lst` 上调用 `CountInto` 时会导致一个编译器错误,因为 `CountInto` 需要一个 `Appender`,而它的方法 `Append` 只定义在指针上。 在 `lst` 上调用 `LongEnough` 是可以的因为 'Len' 定义在值上。
+
+在 `plst` 上调用 `CountInto` 是可以的,因为 `CountInto` 需要一个 `Appender`,并且它的方法 `Append` 定义在指针上。 在 `plst` 上调用 `LongEnough` 也是可以的,因为指针会被自动解引用。
+
+**总结**
+
+在接口上调用方法时,必须有和方法定义时相同的接收者类型或者是可以从具体类型 `P` 直接可以辨识的:
+
+- 指针方法可以通过指针调用
+- 值方法可以通过值调用
+- 接收者是值的方法可以通过指针调用,因为指针会首先被解引用
+- 接收者是指针的方法不可以通过值调用,因为存储在接口中的值没有地址
+
+将一个值赋值给一个接口赋值时,编译器会确保所有可能的接口方法都可以在此值上被调用,因此不正确的赋值在编译期就会失败。
+
+
+译注:
+
+Go语言规范定义了接口方法集的调用规则:
+
+- 类型 *T 的可调用方法集包含接受者为 *T 或 T 的所有方法集
+- 类型 T 的可调用方法集包含接受者为 T 的所有方法
+- 类型 T 的可调用方法集不包含接受者为 *T 的方法
+
+
+- [目录](directory.md)
+- 上一章:[11.5 测试一个值是否实现了某个接口](11.5.md)
+- 下一节:[11.7 第一个例子:使用Sorter接口排序](11.7.md)

+ 1 - 0
eBook/directory.md

@@ -99,6 +99,7 @@
     - 11.3 [类型断言:如何检测和转换接口变量的类型](11.3.md)
     - 11.3 [类型断言:如何检测和转换接口变量的类型](11.3.md)
     - 11.4 [类型判断:type-switch](11.4.md)
     - 11.4 [类型判断:type-switch](11.4.md)
     - 11.5 [测试一个值是否实现了某个接口](11.5.md)
     - 11.5 [测试一个值是否实现了某个接口](11.5.md)
+    - 11.6 [使用方法集与接口](11.6.md)
 
 
 ## 第三部分:Go 高级编程
 ## 第三部分:Go 高级编程