Golang Interface Link to heading

Golang 中的接口就是一组方法的签名。接口是 Golang 整个类型系统的基石,其他语言的接口是不同组件之间的契约的存在,对契约的实现是强制性的,必须显式声明实现了该接口,这类接口称之为“侵入式接口”。而 Golang 的接口是隐式存在,只要实现了该接口的所有函数则代表已经实现了该接口,并不需要显式的接口声明

// go_interface.go

package main

import (
	"fmt"
	"unsafe"
)

// Golang 中接口可以看作是一组方法的集合
// 当一个类型 T 实现了 I 接口的全部方法 我们可以认为
// T 类型实现了这个接口
// 这里暂时可以认为 T类型是 I 接口的子类(但要清楚 Golang 没有class 继承的概念)

// 定义一个 Person 接口
type Person interface {
	walk()
	take()
	speak()
}

// 定义一个Human 结构体
type Human struct {
	Name string
	Age  int
}

// 定义一个Adult 结构体 引入Human
type Adult struct {
	Human
	WorkAddrs string
}

// Adult 以下三个方法 实现了 Person Interface 中定义的函数
func (a Adult) walk() {
	fmt.Println(a.Name, "Adult walk ")
}

func (a Adult) take() {
	fmt.Println(a.Name, "Adult take ")
}

func (a Adult) speak() {
	fmt.Println(a.Name, "Adult speak")
}

func (a Adult) work() {
	fmt.Println(a.Name, "Adult Work hard")
}

// 定义一个Child 结构体 引入Human
type Child struct {
	Human
	SchoolAddrs string
}

// Child 以下三个方法 实现了 Person Interface 中定义的函数
//
func (c Child) walk() {
	fmt.Println(c.Name, "Child walk ")
}

func (c Child) take() {
	fmt.Println(c.Name, "Child take ")
}

func (c Child) speak() {
	fmt.Println(c.Name, "Child speak")
}

func (c Child) study() {
	fmt.Println(c.Name "Child study")
}

// 接受类型为 Person interface的参数
func personDo(p Person) {
	p.walk()
	p.take()
	p.speak()

	// 类型断言
	// 根据类型执行对应类型的不同方法
	if c, ok := p.(Child); ok {
		c.study()
	} else if c, ok := p.(Adult); ok {
		c.work()
	}

}

func main() {

	a := Adult{
		Human: Human{
			Name: "李建军",
			Age:  45,
		},
		WorkAddrs: "西二旗",
	}
	fmt.Println(unsafe.Pointer(&a.Human.Age))
	fmt.Println(unsafe.Pointer(&a.Age))

	personDo(a)

	c := Child{
		Human: Human{
			Name: "李子涵",
			Age:  9,
		},
		SchoolAddrs: "人大附小",
	}

	personDo(c)
}
$ go run go_interface.go

0xc0000a0190
0xc0000a0190
李建军 Adult walk
李建军 Adult take
李建军 Adult speak
李建军 Adult Work hard
李子涵 Child walk
李子涵 Child take
李子涵 Child speak
李子涵 Child study