go语言中的接口interface

package main;

import "fmt"

//接口interface
//接口是一个或多个方法签名的集合
//只要某个类型拥有该接口的所有方法签名,即算实现该接口。
//接口只有方法声明,没有实现,没有数据字段
//接口可以匿名嵌入其它接口,或嵌入到结构中。

//GO语言中的所有类型都实现了空接口
type Empty interface {
}

type Inf interface {
        getName() string;
        setName(name string);
}

type InfB interface {
        //这里把INF接口嵌入
        Inf;
        getAge() int;
        setAge(age int);
}

type A struct {
        name string;
}

type B struct {
        name string;
        age  int;
}

//结构A实现Inf的接口
func (a *A) getName() string {
        return a.name;
}
func (a *A) setName(name string) {
        a.name = name;
}

//结构B实现InfB的接口
func (b *B) getName() string {
        return b.name;
}
func (b *B) setName(name string) {
        b.name = name;
}
func (b *B) getAge() int {
        return b.age;
}
func (b *B) setAge(age int) {
        b.age = age;
}

//函数test接收一个INF类型的变量
func test(i Inf) {
        fmt.Println("ok");
}

//这里使用空接口类型接收参数
func test2(e Empty) {
        //判断属于哪个接口
        if a, ok := e.(Inf); ok {
                fmt.Println(a, "inf");
        } else if a, ok := e.(InfB); ok {
                fmt.Println(a, "infb")
        }
}

//同上,另一种写法
func test3(e Empty) {
        switch a := e.(type) {
        case Inf:
                fmt.Println(a, "inf");
        case InfB:
                fmt.Println(a, "infb");
        default:
                fmt.Println(a, "no");
        }
}

func main() {
        a := A{};
        a.setName("test");
        fmt.Println(a, a.getName());
        //注意这里需要用取地址符,因为上面的方法绑定都是(a *A)
        test(&a);
        test2(&a);
        test3(&a);

        b := B{};
        b.setName("testb");
        b.setAge(25);
        fmt.Println(b.getName(), b.getAge());
        //结构B实现了Inf和InfB两个接口
        test(&b);
        test2(&b);
        test3(&b);

        //接口InfB可以转化为Inf,但Inf不能转化为InfB
        //只能从超集向子集转
        c := B{};
        //注意这里要传地址
        var d Inf = Inf(&c);
        d.setName("testc");
        fmt.Println(d, d.getName());
}