golang接口interfance

一、基本介绍

interfance类型可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量,到某个自定义类型要使用时,在根据具体情况把这些方法写出来

二、基本语法

type 接口名 interfance{
	method1(参数列表)返回值列表
	method2(参数列表)返回值列表
}

例子:

package main

import (
	"fmt"
)

type Usb interface {
	Start()
	Stop()
}
type Phone struct {
}

// 让Phone实现Usb接口方法
func (phone Phone) Start() {
	fmt.Println("手机开始工作...")
}

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

type Camera struct {
}

// 让Camera实现Usb接口方法
func (camera Camera) Start() {
	fmt.Println("相机开始工作...")
}

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

type Computer struct {
}

// 编写一个方法Working方法,接收一个Usb接口类型变量
// 只要是实现了Usb接口,(所谓实现Usb接口,就是指实现了Usb接口声明所有方法)
func (computer Computer) Working(usb Usb) {
	// 通过usb接口变量来调用Start和Stop方法
	usb.Start()
	usb.Stop()
}

func main() {

	computer := Computer{}
	phone := Phone{}
	computer.Working(phone)
	camera := Camera{}
	computer.Working(camera)
}

输出结果:

手机开始工作...
手机停止工作...
相机开始工作...
相机停止工作...

三、说明

  1. 接口里的所有方法都没有方法体,即接口的方法都是没有实现方法,接口体现了程序设计的多态和高内聚低耦合的思想
  2. Golang中的接口,不需要显示实现,只要一个变量,含有接口类型中的所有方法,那么这个变量就实现了这个接口,因此Golang没有impement关键字

四、注意细节

  1. 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的实例
  2. 接口的所有的方法都没有方法体,即都没有实现的方法
  3. 在Golang中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了这个接口
  4. 一个自定义类型只有实现了某个接口,才能将该自定义类型的实例赋给接口类型
  5. 只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
  6. 一个自定义类型可以实现多个接口
  7. Golang接口中不能有任何变量
  8. 一个接口(比如接口A)可以继承多个别的接口(不如B,C接口),这时如果要实现A接口,也必须将B,C接口的方法全部实现
  9. interfance类型默认是一个指针(引用类型),如果没有对interface初始化就使用,那么会输出nil
  10. 空接口interfance{}没有任何方法体,所以所有类型都实现了空接口,可以指向任意类型

五、接口编程的经典案例

实现对结构体切片的排序:sort.Sort(data interfance)

type Interface interface {
    // Len方法返回集合中的元素个数
    Len() int
    // Less方法报告索引i的元素是否比索引j的元素小
    Less(i, j int) bool
    // Swap方法交换索引i和j的两个元素
    Swap(i, j int)
}
package main

import (
	"fmt"
	"math/rand"
	"sort"
)

type Hero struct {
	Name string
	Age  int
}

type Heros []Hero

// 实现Interfance接口
//
func (heros Heros) Len() int {
	return len(heros)
}

// Less方法就是决定你使用什么标准排序
// 索引i的元素是否比索引j的元素小(j=i-6)
// 按照Hero的年龄从小到大排序
func (heros Heros) Less(i, j int) bool {
	return heros[i].Age < heros[j].Age
}

// 交换索引i和j的两个元素
func (heros Heros) Swap(i, j int) {
	heros[i], heros[j] = heros[j], heros[i]
}

func main() {
	var heros Heros
	for i := 0; i < 10; i++ {
		hero := Hero{
			Name: fmt.Sprintf("英雄%d", rand.Intn(100)),
			Age:  rand.Intn(100),
		}
		heros = append(heros, hero)
	}
	// 排序前

	fmt.Println("..........排序前..........")
	for _, v := range heros {
		fmt.Println(v)
	}
	fmt.Println("..........排序前..........")
	// 排序后
	sort.Sort(heros)
	fmt.Println("..........排序后..........")
	for _, v := range heros {
		fmt.Println(v)
	}
	fmt.Println("..........排序后..........")

}

输出结果:

..........排序前..........
{英雄81 87}
{英雄47 59}
{英雄81 18}
{英雄25 40}
{英雄56 0}
{英雄94 11}
{英雄62 89}
{英雄28 74}
{英雄11 45}
{英雄37 6}
..........排序前..........
..........排序后..........
{英雄56 0}
{英雄37 6}
{英雄94 11}
{英雄81 18}
{英雄25 40}
{英雄11 45}
{英雄47 59}
{英雄28 74}
{英雄81 87}
{英雄62 89}
..........排序后..........
posted @ 2021-05-31 23:19  若雨蚂蚱  阅读(108)  评论(0编辑  收藏  举报