未完结 后续补充

接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。

接口

本章学习目标

  • 了解为什么需要接口以及接口的特点
  • 掌握接口的声明和使用
  • 掌握接口值的概念
  • 掌握空接口的特点及其使用场景

为什么要有接口

快速入门 模拟上述图片中的应用场景

type Usb interface {
	Start()
	Stop()
}

type Phone struct {
}

type Camera struct {
}

func (p Phone) Start() {
	fmt.Println("手机开始工作...")
}

func (p Phone) Stop() {
	fmt.Println("手机停止工作...")
}

func (c Camera) Start() {
	fmt.Println("相机开始工作...")
}

func (c Camera) Stop() {
	fmt.Println("相机停止工作...")
}

// Computer 计算机
type Computer struct {
}

func (c Computer) Working(usb Usb) {
	usb.Start()
	usb.Stop()
}
func main() {
    var c = Computer{}
    var p = Phone{}
    var ca Camera
    co.Working(p)
    co.Working(ca)
}

接口的定义

每个接口类型由任意个方法签名组成,接口的定义格式如下:

type 接口类型名 interface{
    方法名1( 参数列表1 ) 返回值列表1
    方法名2( 参数列表2 ) 返回值列表2
    
}
  • 接口类型名:Go语言的接口在命名时,一般会在单词后面添加er,如有写操作的接口叫Writer,有关闭操作的接口叫closer等。接口名最好要能突出该接口的类型含义。
  • 方法名:当方法名首字母是大写且这个接口类型名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。
  • 参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以省略。

注意事项和细节

  1. 接口本身不能创建实例 但可以指向一个实现了该接口的自定义类型的变量(实例)
type People interface {
	Say()
}
type Stu struct {
	Name string
}
func (s *Stu) Say() {
	fmt.Println(s.Name, "say ...")
}
func main() {
    var i People = &Stu{"十二"} // 结构体变量实现了say 实现了接口People
    i.Say()
}
  1. 接口中所有的方法都没有方法体
  2. 在Golang中 一个自定义类型将某个接口的方法都实现 我们就说该自定义类型实现了该接口
  3. 只要是自定义类型都可以实现接口 不仅仅是结构体
//自定义一个数据类型
type MyInt int
//实现Say方法
func (m MyInt) Say() {
	fmt.Println("say a number-->", m)
}
func main() {
	var myint MyInt = 10
	//定义一个接口把 myint 赋值给该接口
	var i People = myint
	i.Say()
}
  1. 一个自定义类型可以实现多个接口
  2. Golang接口中不能有任何变量
  3. interface类型默认是一个指针(引用类型) 如果没有对interface初始化就使用 那么输出nil
  4. 空接口interfa{}没有任何方法 所以所有类型都实现了空接口 即我们可以把任何变量赋值给空接口

接口的最佳实践

type Person struct {
	Name string
	Age  int
}

func (p Person) String() string {
	return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

// ByAge implements sort.Interface for []Person based on
// the Age field.
type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func main() {
	people := []Person{
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}

	fmt.Println(people)
	// There are two ways to sort a slice. First, one can define
	// a set of methods for the slice type, as with ByAge, and
	// call sort.Sort. In this first example we use that technique.
	sort.Sort(ByAge(people))
	fmt.Println(people)

	// The other way is to use sort.Slice with a custom Less
	// function, which can be provided as a closure. In this
	// case no methods are needed. (And if they exist, they
	// are ignored.) Here we re-sort in reverse order: compare
	// the closure with ByAge.Less.
	sort.Slice(people, func(i, j int) bool {
		return people[i].Age > people[j].Age
	})
	fmt.Println(people)