思想:

duck typing - 鸭子类型:
当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
意思就是说:
研究一个东西究竟是不是鸭子,取决于它能不能满足鸭子的工作。

接口:

go通过接口实现了类型安全的鸭子类型,同时又避免了OOP编程中的继承,我们来学习下go的接口(interface)。
go的接口是一种抽象的可以自定义的类型,没法直接实例化,它声明了一个或者多个方法的签名。
如果一个 struct 实现了一个 接口定义的所有方法 ,我们就说这个 struct 实现了这个 接口

注意:
这里的“实现”是隐式的,你不用显示声明某个struct实现了哪个接口。

实例:

首先,我们通过 interface 声明一个接口:

// Sleeper 接口声明
type Sleeper interface {
    Sleep() // 声明一个 Sleep() 方法
}

下面,我们定义两个类型:

//定义一个 Dog 的结构体,其中有 1 个 Name 属性。
type Dog struct {
    Name string
}
//思路:
//    我们如果想实现上面的 Sleeper接口,那么只要实现其中的方法即可。
//    下面我们为 Dog 添加一个方法 Sleep() :
func (d Dog) Sleep() {
    fmt.Printf("Dog %s is sleeping\n", d.Name)
}

//我买再定义一个 Cat 的结构体,其中有 1 个 Name 属性。
type Cat struct {
    Name string
}
func (c Cat) Sleep() {
    fmt.Printf("Cat %s is sleeping\n", c.Name)
}

测试:

//参数: 只要是 Sleeper类型,都可以传入。
//        即只要是实现了这个接口的,都可以当做参数传进来。
func AnimalSleep(s Sleeper) {
    s.Sleep()
}


func main() {
    var s Sleeper

    dog := Dog{Name: "xiaobai"}
    cat := Cat{Name: "hellokitty"}

    //思路:只要 dog 这个实例的类型实现了 Sleeper接口中的方法,就认为dog实现了Sleeper这个接口。
    s = dog
    AnimalSleep(s) // 使用 dog 的 Sleep()
    s = cat
    AnimalSleep(s) // 使用 cat 的 Sleep()

      //创建一个 Sleeper 切片
    sleepList := []Sleeper{Dog{Name: "xiaobai"}, Cat{Name: "kitty"}}
    for _, s := range sleepList {
        s.Sleep()
    }
}

到这里我们就用 go 的接口实现了多态,我们先声明了一个接口类型的值,只要实现了这个接口的 struct 变量(dog cat),都可以赋值给它(Sleeper接口变量 s), 而调用方法的时候,go 会根据实际类型选择使用哪个 struct 的方法。


来源: