>

interface 类型在 Go 语言中是一个核心类型,用途及其广泛,本文列举其中最主要的使用场景,详述其使用方式,从而掌握使用它的精髓。


#### 1. interface 接口类型做参数 ---

想要函数对任何类型都能处理,并且处理后返回,可以把参数设置成接收 duck type,然后通过参数返回。
传入的实参为指针类型的对象,也即相应的 对象 通过 pointer receiver 来实现 type Entity interface {} 中指定的方法。
或者,可以通过 把 duck type 通过返回值传出,然后调用方通过 type assertion 来得到具体的类型。

(1) interface declaration

1
2
3
type Entity interface {
Clone() Entity
}

(2) interface as function return value

1
2
3
func clone(ent Entity) Entity {
return ent.Clone()
}

The structs that implements the interface

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
type Human struct {
Sex string
Ct *Creature
}

type Creature struct {
Category string
}

func (this *Human) Clone() Entity { // 注意:这里的返回值需要是 Entity 而不能是 *Human,否则不匹配(1) 中的 Entity 的 interface 定义。
p := &Human{}
p.Sex = this.Sex
p.Ct = this.Ct.Clone()
return p
}


func main() {

hm := &Human{Sex: "Male", Ct: &Creature{Category: "Mammal"}}
tmp := clone(hm)
hm1, ok := tmp.(*Human)
if !ok {
fmt.Println("Failed: hm1 is not a human pointer!")
} else {
fmt.Println("OK: hm1 is a human pointer!")
}
fmt.Println(reflect.TypeOf(hm1))
fmt.Println(hm1)
}

#### 2. Pointer Receiver ---

Note that we use a pointer receiver to implement the function, if we do not use pointer receiver to implement the interface declared function,
when it is passed as a ducktype argument in function, we won’t be able to modify the instance.

e.g.

Output:
{1}
{1}

As shown above, the modification of sch in change() function will not take effect!.

ponter receiver 使用要点:
如果 struct 的成员函数需要修改对应对象的字段,必须设置 pointer receiver!

比如:

其他情况下,只要不涉及到 struct 成员变量的修改,并且不是 duck type 的实现,可以互用。

但是注意:
如果定义一个 duck type,那么用如果用 pointer receiver 实现其中的方法的话,只有指针类型是该 duck type 类型,value 类型则不是 duck type。

注意:
只要函数实现的地方使用了 pinter receiver 去实现,那么调用的地方,用对象的指针去调用,和用对象去调该函数,效果一样。

比如:

  1. 把 interface 接口 作为 struct 成员,即可以是匿名成员,也可以是实名成员。

#### 3. 接口类型数组 ---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
type entity interface {
Print(string)
}

type Person struct {
Name string
}

type Identity struct {
Title string
}

func (person Person) Print() {
person.Name = person.Name
}

func (iden Identity) Print() {
iden.Title = iden.Title
}

func test_slice(ents []entity) {
for _, v := range ents {
v.Print()
}
}

func main() {
per := new(Person)
id := Identity{"Boss"}
ss := []entity{per, per1}
test_slice(ss)
}

4. json 编解码 entity 类型