golang接口使用说明与经典案例

接口在golang中使用的特别多,在此加以简单的总结:

golang接口使用说明:

(1)空接口(没有任何方法的接口)可以看成是万能数据类型,可以接收任意类型的数据;如果是包含方法的接口,给该接口赋值,对应的值对象需要实现该接口的所有方法才可以。

 (2)接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量(实例)

(3)接口中的所有方法都没有方法体,即都是没有实现的方法。

(4)在golang中,一个自定义类型需要将该接口对应的方法都实现,才能说该类型实现了该接口。

(5)只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型。

(6)一个自定义类型,可以同时实现多个接口。(如可以同时实现 A接口  B接口)

(7)若两个接口包含一样的方法,一个自定义类型实现了所有的方法,则该类型实现了这两个接口。接口的实现主要是通过方法来标记,而不是接口名称。

(8)接口类型默认是一个指针(引用类型),如果没有初始化就使用,就会输出nil。

(9)golang接口中,不能包含任意变量。

package main

import "fmt"

type USB interface {
	working()
	stop()
}
type USB1 interface {
	working()
	stop()
}

//定义Phone对象
type Phone struct {
}

//定义Cameron对象
type Cameron struct {
}

//定义Computer对象
type Computer struct {
}

//分别让两个对象实现USB的方法
func (p Phone) working() {
	fmt.Println("手机开始工作。。。")
}
func (p Phone) stop() {
	fmt.Println("手机停止工作")
}
func (c Cameron) working() {
	fmt.Println("照相机开始工作。。。")
}
func (c Cameron) stop() {
	fmt.Println("照相机停止工作")
}
func (c Computer) work(usb USB) { //具有相同接口的对象(struct)都可以作为函数参数(包含多态、高内聚低耦合的思想)
	usb.working()  //根据上下文判断是Cameron 还是 phone,实现了多态
	usb.stop()
}

//自定义类型的变量 都可以实现接口,不一定是struct
type MyInt int

func (i MyInt) working() {
	fmt.Println("自定义类型的  working() 方法")
}
func (i MyInt) stop() {
	fmt.Println("自定义类型的  stop() 方法")
}
func main() {
	c := Computer{}
	ca := Cameron{}
	ph := Phone{}
	c.work(ca) //由于Cameron实现了USB的接口,所以类型可以和USB进行匹配
	c.work(ph) //由于phone实现了USB的接口,所以类型可以和USB进行匹配
	fmt.Println("------------")
	var usb USB
	var myInt MyInt
	usb = myInt //赋值给接口(包含方法),myInt需要实现该接口的所有方法。
	usb.stop()
	myInt.working()
}

/*
    特别说明:  golang中实现接口不需要显示来实现(Java中通过关键字,golang中接口对应的方法来实现)
                如程序所示,对象通过 working()、stop()方法的实现,实现了接口USB、USB1.所以,接口与接口的方法相关,与接口名称无关。
                如果要实现接口,就要实现接口里的所有方法。

*/

案例:

使用sort包下的Sort对复杂结构类型的数据进行排序:

golang接口使用说明与经典案例_第1张图片

该方法的参数为:interface类型,如果要进行排序,需要按照对应的参数传值。对应的interface参数结构如下:

golang接口使用说明与经典案例_第2张图片

此接口是包含方法的接口,非空接口。传递的参数需要实现3个方法,

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

特别说明:要实现接口必须为自定义类型(type XX  数据类型,结构体也可以看成是一种自定义类型)。


package main

import (
	"fmt"
	"math/rand"
	"sort"
	"strconv"
	"time"
)
type Student struct {
	Name string
	Age int
	Score int
}
//var MyData []Student
type Mydata []Student  //  注意:是自定义类型  Mydata 实现接口对应的方法
func (s *Mydata) Len() int {
	return len(*s)  //// Len方法返回集合中(需要排序集合)的元素个数
}
func (s *Mydata)Less(i, j int) bool {
	return  (*s)[i].Score>(*s)[j].Score  //依据什么排序  (  > 降序, <  升序)
}
func (s *Mydata) Swap(i, j int)  {
	//交换那些数据
	(*s)[i].Score,(*s)[j].Score=(*s)[j].Score,(*s)[i].Score
	(*s)[i].Name,(*s)[j].Name=(*s)[j].Name,(*s)[i].Name
	(*s)[i].Age,(*s)[j].Age=(*s)[j].Age,(*s)[i].Age
}

func main() {
	var studentInfor Mydata
	studentInfor=make([]Student,0)
	rand.Seed(time.Now().Unix())
	for i:=0;i<10;i++{
		name:="jiangzhou"+strconv.Itoa(i)
		score:=rand.Intn(100)
		age:=rand.Intn(5)+20
		stu:=Student{Name:name,Age:age,Score:score}
		studentInfor=append(studentInfor,stu)
	}
	fmt.Println("排序之前的数据为:")
	for _,v:=range studentInfor{
		fmt.Printf("姓名:%s,   age:%d,   socre:%d\n",v.Name,v.Age,v.Score)
	}
	//调用goland sort包下的Sort方法,该方法接收interface类型参数,需要实现对应的3个方法
	/*
	type Interface interface {
    // Len方法返回集合中的元素个数
    Len() int
    // Less方法报告索引i的元素是否比索引j的元素小
    Less(i, j int) bool
    // Swap方法交换索引i和j的两个元素
    Swap(i, j int)
}
	*/
	sort.Sort(&studentInfor)
	fmt.Println("\n排序之后的数据为:")
	for _,v:=range studentInfor{
		fmt.Printf("姓名:%s,   age:%d,   socre:%d\n",v.Name,v.Age,v.Score)
	}

}

 

golang接口使用说明与经典案例_第3张图片

实现接口 与 继承的 区别

(1)当A结构体继承了B结构体,则A结构体就自动拥有了B结构体的方法和字段,并且可以直接使用。

(2)当A接口需要扩展功能,同时不希望去破坏继承关系时,则可以去实现某一个接口即可。因此可以认为:实现接口是对继承机制的补充。

实现接口可以看做是对 继承的一种补充

有如下需求:如果要让足球运动员、大学生都要掌握英语技能,可以采用2种方法:(1)足球运动员绑定一个英语方法,大学生绑定一个英语方法。(2)写一个英语技能的接口,足球运动员、大学生实现此接口。很显然方法2保证了实现方法(技能要求)的一致性。

golang接口使用说明与经典案例_第4张图片golang接口使用说明与经典案例_第5张图片

你可能感兴趣的:(Golang)