Golang接口(interface)

252 阅读4分钟

接口(interface)

接口可以定义一组方法但不需要实现,并且接口不能包含任何变量,到某个自定义类型(如结构体)要使用的时候,在根据具体情况把这些方法写出来。

基本语法

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

实现接口所有方法

func (t 自定义类型) method1(参数列表) 返回值列表 {
    //  方法实现
}
func (t 自定义类型) method12参数列表) 返回值列表 {
    //  方法实现
}

说明

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

代码示例

package main

import "fmt"

// 定义一个USB接口
type Usb interface {
	Start()
	Stop()
}
// phone结构体
type Phone struct {
}
// Phone 实现接口所有方法
func (p Phone) Start() {
	fmt.Println("手机开始工作。。。")
}
func (p Phone) Stop() {
	fmt.Println("手机停止工作。。。")
}

// 相机结构体
type Camera struct {
}
// Camera 实现接口所有方法
func (c Camera) Start() {
	fmt.Println("相机开始工作.....")
}
func (c Camera) Stop() {
	fmt.Println("相机停止工作...")
}

type Computer struct {
}
// 方法Working  接收一个USB接口类型变量
// 只要实现了 Usb接口
func (c Computer) Working(usb Usb) {
	usb.Start()
	usb.Stop()
}

func main() {
	computer:= Computer{}
	phone := Phone{}
	camera := Camera{}

	computer.Working(phone)
	computer.Working(camera)

}

输出结果:

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

注意事项

  1. 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量(实例) 代码示例:
package main

import "fmt"

type AInterface interface {
	Say()
}

type Stu struct {
	Name string
}

func (s Stu) Say() {
	fmt.Println("stu Say()")
}
func main() {
	var s Stu
	var a AInterface = s
	a.Say()
}
// 输出: stu Say()
  1. 接口中所有的方法都没有方法体即都是没有实现的方法
  2. 在Golang中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类实现了该接口
  3. 一个自定义接口实现了某个接口才能将该自定义的实例(变量)赋给接口类型
  4. 只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型
type AInterface interface {
	Say()
}

// 自定义类型
type integer int

func (i integer) Say() {
	fmt.Println("integer Say i= ", i)
}
func main() {
	var i integer = 10
	var b AInterface = i
	b.Say()
}
  1. 一个自定义类型可以实现多个接口
type AInterface interface {
	Say()
}

type BInterface interface {
	Hello()
}

type Monster struct {

}

func (m  Monster) Hello() {
	fmt.Println("Monster Hello  ")
}

func (m  Monster) Say() {
	fmt.Println("Monster Say  ")
}
func main() {
	// Monster 实现了 AInterface  和 BInterface
	var m Monster
	var a2 AInterface = m
	var b2 BInterface = m
	a2.Say()
	b2.Hello()
}
  1. interface类型默认是一个指针(引用类型),如果没有对interface初始化就使用那么会输出nil
  2. 空接口interface{}没有任何方法,所以所有类型都实现了空接口
// 空接口
type T interface {

}

func main() {
	var s Stu
	var a AInterface = s
	a.Say()

	// 可以给空接口赋值
	var t = s
	fmt.Println(t)
	var t2 interface{} = s
	var num1 float64 = 90.0
	t2 = num1
	fmt.Println(t2, t)
}

接口经典应用实例

对一个自定义的结构体 学生按照成绩降序输出学生切片

// 学生结构体
type Stu struct {
	Name  string
	Age   int
	Score float64
}
// 学生切片
type stuSlice []Stu

// 实现排序接口
func (ss stuSlice) Len() int {
	return len(ss)
}

func (ss stuSlice) Less(i, j int) bool {
	return ss[i].Score > ss[j].Score
}

func (ss stuSlice) Swap(i, j int) {
	ss[i], ss[j] = ss[j], ss[i]
}

func main() {
    // 测试
    var students stuSlice
    for i := 0; i < 10; i++ {
        f, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", rand.Float64()*40+60), 64)
        stu := Stu{
            Name:  fmt.Sprintf("学生%d", rand.Intn(100)),
            Age:   rand.Intn(100),
            Score: f,
        }
        students = append(students, stu)
    }
    // 排序前
    fmt.Println("排序前-----------")
    fmt.Println(students)
    sort.Sort(students)
    fmt.Println("排序后-----------")
    fmt.Println(students)
}
// 结果实例:
排序前-----------
[{学生87 47 84.19} {学生81 18 77.51} {学生40 56 62.63} {学生94 11 72.04} {学生89 28 68.57} {学生11 45 78.76} {学生6 95 87.16} {学生28 58 74.43} {学生47 87 71.72}{学生90 15 68.26}]
排序后-----------
[{学生6 95 87.16} {学生87 47 84.19} {学生11 45 78.76} {学生81 18 77.51} {学生28 58 74.43} {学生94 11 72.04} {学生47 87 71.72} {学生89 28 68.57} {学生90 15 68.26} {学生40 56 62.63}]