1.定义

type 接口类型名 interface{
    方法名1( 参数列表1 ) 返回值列表1
    方法名2( 参数列表2 ) 返回值列表2
    …
}

2.假如一个接收者同时拥有了某个接口的所有方法,则该接收者实现了该接口

// Singer 接口
type Singer interface {
	Sing()
}

type Bird struct {}

// Sing Bird类型的Sing方法
func (b Bird) Sing() {
	fmt.Println("汪汪汪")
}

这样就称为Bird实现了Singer接口。

3.接口的使用场景:假如一个函数中不管参数是什么类型,都必须执行某个方法,这个时候我们就可以把需要传进来的类型都去实现这个接口,然后直接调用接口中的必须执行方法即可

4.嵌套接口:就是定义了两个接口,但是现在有个需求需要同时实现这两个接口中的所有方法

// src/io/io.go

type Reader interface {
	Read(p []byte) (n int, err error)
}

type Writer interface {
	Write(p []byte) (n int, err error)
}

// ReadWriter 是组合Reader接口和Writer接口形成的新接口类型
type ReadWriter interface {
	Reader
	Writer
}

5.使用值类型和使用指针类型去实现接口的区别?

使用值类型去实现接口那么,该类型的值类型和指针类型都实现了该接口

使用指针类型去实现接口那么,只有该类型的指针类型实现了该接口

6.空接口可以赋予任何值(不管是int,还是string或者别的都可以直接赋予给空接口,空接口的底层实际分为两部分,动态类型:就是空接口指向值的类型      动态值:就是空接口指向的值)

   空接口类型推断:

  res,ok=指针实例.(推断类型)//假如接口中的动态类型和推断类型相符,res返回对应的值,ok=true,假如不符合,res返回推断类型的零值,ok=false

  空接口类型获取:

  v:=接口实例.(type)会返回对应空接口中的类型

  空接口的使用场景?

  1.因为可以设置为任何参数,可以用来指定函数参数类型

  2.可以用来指定map的value类型