1、 接口定义了一个对象的行为规范
A. 只定义规范,不实现
B. 具体的对象需要实现规范的细节
2、Go中接口定义
A. type 接口名字 interface
B. 接口里面是一组方法签名的集合
type Animal interface {
    Talk()
    Eat() int
    Run()
}
3、Go中接口的实现
A. 一个对象只要包含接口中的方法,那么就实现了这个接口
B. 接口类型的变量可以保存具体类型的实例
type Animal interface {
    Talk()
    Eat() int
    Run()
}
4、接口实例
A. 一个公司需要计算所有职员的薪水
B. 每个职员的薪水计算方式不同
package main
import (
	"fmt"
)
type Employer interface {
	CalcSalary() float32
}
type Programer struct {
	name  string
	base  float32
	extra float32
}
func NewProgramer(name string, base float32, extra float32) Programer {
	return Programer{
		name:  name,
		base:  base,
		extra: extra,
	}
}
func (p Programer) CalcSalary() float32 {
	return p.base
}
type Sale struct {
	name  string
	base  float32
	extra float32
}
func NewSale(name string, base, extra float32) Sale {
	return Sale{
		name:  name,
		base:  base,
		extra: extra,
	}
}
func (p Sale) CalcSalary() float32 {
	return p.base + p.extra*p.base*0.5
}
func calcALL(e []Employer) float32 {
	var cost float32
	for _, v := range e {
		cost = cost + v.CalcSalary()
	}
	return cost
}
func main() {
	p1 := NewProgramer("搬砖1", 1500.0, 0)
	p2 := NewProgramer("搬砖2", 1500.0, 0)
	p3 := NewProgramer("搬砖3", 1500.0, 0)
	s1 := NewSale("销售1", 800.0, 2.5)
	s2 := NewSale("销售2", 800.0, 2.5)
	s3 := NewSale("销售3", 800.0, 2.5)
	var employList []Employer
	employList = append(employList, p1)
	employList = append(employList, p2)
	employList = append(employList, p3)
	employList = append(employList, s1)
	employList = append(employList, s2)
	employList = append(employList, s3)
	cost := calcALL(employList)
	fmt.Printf("这个月的人力成本:%f\n", cost)
}
5、接口类型变量
A. var a Animal
B. 那么a能够存储所有实现Animal接口的对象实例
package main
import "fmt"
type Animal interface {
	Talk()
	Eat()
	Name() string
}
type Dog struct {
}
func (d Dog) Talk() {
	fmt.Println("汪汪汪")
}
func (d Dog) Eat() {
	fmt.Println("我在吃骨头")
}
func (d Dog) Name() string {
	fmt.Println("我的名字叫旺财")
	return "旺财"
}
type Pig struct {
}
func (d Pig) Talk() {
	fmt.Println("坑坑坑")
}
func (d Pig) Eat() {
	fmt.Println("我在吃草")
}
func (d Pig) Name() string {
	fmt.Println("我的名字叫八戒")
	return "八戒"
}
func testInterface1() {
	var d Dog
	var a Animal
	a = d
	a.Eat()
	a.Talk()
	a.Name()
	var pig Pig
	a = pig
	a.Eat()
	a.Talk()
	a.Name()
}
func just(a Animal) {
	// d, ok := a.(Dog)
	// p, ok := a.(Pig)
	switch v := a.(type) {
	case Dog:
		fmt.Printf("v is dog, %v\n", v)
	case Pig:
		fmt.Printf("v is dog, %v\n", v)
	default:
		fmt.Printf("not support")
	}
}
func testInterface2() {
	var d Dog
	just(d)
}
func main() {
	//testInterface1()
	testInterface2()
}
1、空接口
A. 空接口没有定义任何方法
B. 所以任何类型都实现了空接口
interface {
}
package main
import "fmt"
func describe(a interface{}) {
	fmt.Printf("%T %v\n", a, a)
}
func testInterface() {
	var a interface{}
	var b int = 100
	a = b
	fmt.Printf("%T %v\n", a, a)
	var c string = "hello"
	a = c
	fmt.Printf("%T %v\n", a, a)
	var d map[string]int = make(map[string]int, 100)
	d["abc"] = 1000
	d["eke"] = 30
	a = d
	fmt.Printf("%T %v\n", a, a)
}
type Student struct {
	Name string
	Sex  int
}
func main() {
	a := 65
	describe(a)
	str := "hello"
	describe(str)
	var stu Student = Student{
		Name: "user01",
		Sex:  1,
	}
	describe(stu)
}
2、类型断言
A. 如何获取接口类型里面存储的具体的值呢?
B.类型断言的坑
C.如何解决,引入 ok判断机制! v, ok := i.(T)
D.type switch。
E.type switch另外一种写法,解决转两次的问题
package main
import "fmt"
// 类型断言
func test(a interface{}) {
	s, ok := a.(int)
	if ok {
		fmt.Println(s)
		return
	}
	str, ok := a.(string)
	if ok {
		fmt.Println(str)
		return
	}
	f, ok := a.(float32)
	if ok {
		fmt.Println(f)
		return
	}
	fmt.Println("can not define the type of a")
}
func testInterface1() {
	var a int = 100
	test(a)
	var b string = "hello"
	test(b)
}
// case优雅实现(二次转换)
func testSwitch(a interface{}) {
	switch a.(type) {
	case string:
		fmt.Printf("a is string, value: %v", a.(string))
	case int:
		fmt.Printf("a is int, value: %v", a.(int))
	case int32:
		fmt.Printf("a is not, value: %v", a.(int32))
	default:
		fmt.Println("no support type")
	}
}
func testInterface2() {
	var a int = 100
	testSwitch(a)
	var b string = "hellow"
	testSwitch(b)
}
// case优雅实现(一次转换)
func testSwitch2(a interface{}) {
	switch v := a.(type) {
	case string:
		fmt.Printf("a is string, value: %v", v)
	case int:
		fmt.Printf("a is int, value: %v", v)
	case int32:
		fmt.Printf("a is not, value: %v", v)
	default:
		fmt.Println("no support type")
	}
}
func testInterface3() {
	var a int = 100
	testSwitch2(a)
	var b string = "hellow"
	testSwitch2(b)
}
func main() {
	testInterface1()
	testInterface2()
	testInterface3()
}
1、指针接收
package main
import "fmt"
type Animal interface {
	Talk()
	Eat()
	Name() string
}
type Dog struct {
}
func (d *Dog) Talk() {
	fmt.Println("汪汪汪")
}
func (d *Dog) Eat() {
	fmt.Println("我在吃骨头")
}
func (d *Dog) Name() string {
	fmt.Println("我的名字叫旺财")
}
func main() {
	var a Animal
	// 值
	// a存的是一个值类型的Dog,那么调用a.Eat(). &Dog ->Eat()
	// 如果一个变量存储在接口类型的变量中之后,那么不能获取这个变量的地址
	//var d Dog
	//a = d
	//a.Eat()
	//
	//fmt.Printf("%T %v\n", a, a)
	// 指针
	var d1 *Dog = &Dog{}
	a = d1
	// *(&Dog).Eat()
	a.Eat()
	fmt.Printf("*Dog %T %v\n", d1, d1)
}
1、 实现多接口,同一个类型可以实现多个接口
2、 接口嵌套,和结构体嵌套类似
package main
import "fmt"
type Animal interface {
	Talk()
	Eat()
	Name() string
}
type PuruDongwu interface {
	TaiSheng()
}
type Dog struct {
}
func (d Dog) Talk() {
	fmt.Println("汪汪汪")
}
func (d Dog) Eat() {
	fmt.Println("我在吃骨头")
}
func (d Dog) Name() string {
	fmt.Println("我的名字叫旺财")
	return "旺财"
}
func (d Dog) TaiSheng() {
	fmt.Println("狗是胎生的")
}
func main() {
	var d Dog
	var a Animal
	fmt.Printf("%v %T %p", a, a, a)
	if a == nil {
		fmt.Println("a is nil")
	}
	a = d
	a.Eat()
	var b PuruDongwu
	b = d
	b.TaiSheng()
}
原文:https://www.cnblogs.com/wangshuyang/p/11815147.html