简单地说,接口就是一组方法签名的组合。我们使用一个接口来识别一个对象能够进行的操作。一个接口可以被任意数量的类型满足,而且一个类型可以实现任意数量的接口。每个类型都实现了一个空接口interface{}。
如果你声明了一个接口变量,这个变量能够存储任何实现该接口的对象类型。
package mainimport "fmt"type Human struct {name stringage intphone string}type Student struct {Human //an anonymous field of type Humanschool stringloan float32}type Employee struct {Human //an anonymous field of type Humancompany stringmoney float32}//A human method to say hifunc (h Human) SayHi() {fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)}//A human can sing a songfunc (h Human) Sing(lyrics string) {fmt.Println("La la la la...", lyrics)}//Employee's method overrides Human's onefunc (e Employee) SayHi() {fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,e.company, e.phone) //Yes you can split into 2 lines here.}// Interface Men is implemented by Human, Student and Employee// because it contains methods implemented by them.type Men interface {SayHi()Sing(lyrics string)}func main() {mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}Tom := Employee{Human{"Sam", 36, "444-222-XXX"}, "Things Ltd.", 5000}//a variable of the interface type Menvar i Men//i can store a Studenti = mikefmt.Println("This is Mike, a Student:")i.SayHi()i.Sing("November rain")//i can store an Employee tooi = Tomfmt.Println("This is Tom, an Employee:")i.SayHi()i.Sing("Born to be wild")//a slice of Menfmt.Println("Let's use a slice of Men and see what happens")x := make([]Men, 3)//These elements are of different types that satisfy the Men interfacex[0], x[1], x[2] = paul, sam, mikefor _, value := range x {value.SayHi()}}
输出是:
This is Mike, a Student:Hi, I am Mike you can call me on 222-222-XXXLa la la la... November rainThis is Tom, an Employee:Hi, I am Sam, I work at Things Ltd.. Call me on 444-222-XXXLa la la la... Born to be wildLet’s use a slice of Men and see what happensHi, I am Paul you can call me on 111-222-XXXHi, I am Sam, I work at Golang Inc.. Call me on 444-222-XXXHi, I am Mike you can call me on 222-222-XXX
从上面的代码可以看出,接口类型是一组抽象的方法集,它本身不实现方法或者精确描述数据结构和方法的实现方式。接口本身并不关心到底是什么数据类型实现了它。接口类型的本质就是如果一个数据类型实现了自身的方法集,那么该接口类型变量就能够引用该数据类型的值。
空接口类型interface{}一个方法签名也不包含,所以所有的数据类型都实现了该方法。
空接口类型在描述一个对象实例的形式上力不从心,但是当我们需要存储任意数据类型的实例的时候,空接口类型的使用使得我们得心应手。

