当一只鸟走路像鸭子,游泳像鸭子,叫起来也像鸭子,那么我们就认为它就是鸭子。
Duck typing 的理念因此比喻得名。
Golang 通过 interface 实现 duck typing。 Effective Go 文章中这样描述 interface: interface
指定了一种描述对象行为的方法:如果某样东西可以做这件事,这样东西就可以用在这里。
再具体讲, 就是当某个变量的类型实现了某个接口的所有方法 (这个时候可以称该类型实现
满足该接口) ,那么这个变量就能用在要求这个接口的地方。
package mainimport ("reflect""fmt" )type Test struct { }func (this *Test)test() {fmt.Println("in test()") }type Tester interface {test() }func MakeTest1(v Tester) {fmt.Printf("\nIn Maketest1\n")v.(Tester).test() }func MakeTest2(v interface{}) {fmt.Printf("\nIn Maketest2\n")v.(Tester).test() }func main() {t := new(Test)var ti Testerti = tti.test()// 接口类型断言// value为Test类型的对象// 是ti的值value := ti.(Tester)fmt.Printf("\n方式1:\n")fmt.Println(reflect.TypeOf(value))value.test()// v是ti的值,是Test类型// Tester是接口类型if v, ok := ti.(Tester); ok {fmt.Printf("\n方式2:\n")fmt.Println(reflect.TypeOf(v))v.test()}// switch type专用组合// 如果需要在if中判断可以用上面的形式switch t := ti.(type) {case Tester:fmt.Printf("\n方式3:\n")fmt.Println("Tester")fmt.Println(reflect.TypeOf(t))t.test()default:fmt.Println("Unknow")}// 传递Test结构变量// 因为Test实现了Tester接口 MakeTest1(t)// 传递Tester接口变量 MakeTest1(ti)// 传递Test结构变量// 因为Test实现了interface{}接口 MakeTest2(t)// 传递Tester接口变量// 因为任何类型都实现了interface{} MakeTest2(ti)}
运行结果:
in test()方式1: *main.Test in test()方式2: *main.Test in test()方式3: Tester *main.Test in test()In Maketest1 in test()In Maketest1 in test()In Maketest2 in test()In Maketest2 in test()
Golang 里面有个空的接口 interface{}, 大括号里看上去什么也没有, 但认为它有一个空
的方法;Golang 里的每一种类型或者你自定义的类型,不管有没有添加了什么具体的方法,
都认为有一个空的方法。因此每种类型自动实现了 interface{}接口,要求 interface{}的地方
就可以用任意类型的变量。
下载interface.go