Golang 学习——interface 接口学习(一)

Golang 中接口定义及实现,空接口,接口嵌套学习#

Golang 中,接口是一组方法签名。当类型为接口中的所有方法提供定义时,它被称为实现接口。它与 OOP(面向对象编程) 非常相似。接口指定了类型应该具有的方法,类型决定了如何实现这些方法。

如果某个对象实现了某个接口的所有方法,则此对象就实现了该接口。

一。接口定义及实现#

1. 定义接口#

关键字 interface 用来定义接口,语法如下:

type interface_name interface {
   method_name1([args ...arg_type]) [return_type]
   method_name2([args ...arg_type]) [return_type]
   method_name3([args ...arg_type]) [return_type]
   ...
   method_namen([args ...arg_type]) [return_type]
}

一个接口中可以定义多个方法,根据逻辑需要,自定义参数和返回值。

2. 实现接口#

一个结构体实现了某个接口的所有方法,则此结构体就实现了该接口。

我们定义一个 Phone 接口,包含两个方法 call()sendMessage()

type Phone interface {
    call()
    seenMessage()
}

声明结构体,用来实现接口:

type Huawei struct {
    name  string
    price float64
}

type Xiaomi struct {
    name  string
    price float64
}

声明了 HuaweiXiaomi 两个结构体,各包含 nameprice 两个字段。

接下来,实现 Phone 接口,我们先让 Huawei 结构体实现该接口所有方法:

func (huawei Huawei) call() {
    fmt.Printf("%s 有打电话功能.....\n", huawei.name)
}

func (huawei Huawei) seenMessage() {
    fmt.Printf("%s 有发短信功能.....\n", huawei.name)
}

初始化 Huawei 结构体,测试接口的方法:

mate30 := Huawei{
    name:  "Mate 30",
    price: 6999,
}
mate30.call()
mate30.seenMessage()

输出:

Mate 30 有打电话功能.....
Mate 30 有发短信功能.....

Huawei 结构体实现了 Phone 接口的所有方法,那就认为,则 Huawei 结构体实现了 Phone 接口。

那如何判断是否实现了该接口,可参考:
Golang 学习 —— 如何判断 Golang 接口是否实现?

我们具体也操作下,看看 Xiaomi 结构体若没有实现 Phone 接口会发生什么?

实现 Phone 接口一个方法:

func (xiaomi Xiaomi) seenMessage() {
    fmt.Printf("%s 只有发短信功能.....\n", xiaomi.name)
}

Xiaomi 只实现了 Phone 的 发短信方法,所以认为 Xiaomi 类型未实现了 Phone 接口。我们具体验证下:

首先初始化 Xiaomi 结构体,并测试方法

xiaomi9 := Xiaomi{
    name:  "Xiao 9",
    price: 4999,
}
xiaomi9.seenMessage()

输出:

Xiao 9 只有发短信功能.....

seenMessage() 方法测试没问题,我们使用 new() 函数来测试下 Xiaomi 结构体是否实现了 Phone 接口:

var _ Phone = new(Xiaomi)

下图是我从自己的 IDE(Goland)截的图,为了方便记录,我将上下文的代码专门换行隔开了。

在这里插入图片描述

从图中可以看到,new 下方有红线,鼠标浮上去会显示错误信息,大意就是:Xiaomi 未实现 Phone 接口的某些方法,如:call(),因此不能将 Xiaomi 用作电话类型。

二。空接口#

空接口 interface{}
不包含任何的方法,正因为如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值。

fmt 包下的 Print 系列函数,其参数大多是空接口类型,也可以说支持任意类型:

func Print(a ...interface{}) (n int, err error)
func Println(format string, a ...interface{}) (n int, err error)
func Println(a ...interface{}) (n int, err error)

1. 实例#

我们定义一个空接口练习下:

// 定义一个空接口
type Empyt_interface interface {
}

// 定义一个入参为任意类型的函数
func getInfo(arg Empyt_interface) {
    fmt.Println("getInfo 函数.....", arg)
}
// 也可以写成如下形式,更推荐
func getInfo2(arg interface{}) {
    fmt.Println("getInfo2 函数.....", arg)
}

Golang 很多库的源代码都会以空接口作为参数,表示接受任意类型的参数

我们自己也实战一下:

定义一个值为任意类型的 map

map1 := make(map[string] interface{})
map1["数字"] = 1
map1["字符串"] = "字符串"
map1["布尔"] = false
fmt.Println("map1 ...........", map1)

输出:

map1 ........... map[字符串:字符串 布尔:false 数字:1]

三。接口嵌套#

顾名思义,接口嵌套就是一个接口中包含了其他接口,如果要实现外部接口,那么就要把内部嵌套的接口对应的所有方法全实现了。

1. 实例#

我们定义 3 个接口,其中有一个接口嵌套了另外两个:

// 定义3个接口
type A interface {
    test1()
}

type B interface {
    test2()
}

// 定义嵌套接口
type C interface {
    A
    B
    test3()
}

接着我们在定义一个结构体,并实现所有方法:

type Person struct {
    //如果想实现接口C,那不止要实现接口C的方法,还要实现接口A,B中的方法
}

func (p Person) test1() {
    fmt.Println("test1 方法................")
}

func (p Person) test2() {
    fmt.Println("test2 方法................")
}

func (p Person) test3() {
    fmt.Println("test3 方法................")
}

初始化结构体,并测试方法:

var person Person = Person{}
// 实现 C 接口的所有方法
person.test1()
person.test2()
person.test3()

输出:

test1 方法................
test2 方法................
test3 方法................

以上就是 Golang 接口的基础学习,总结了接口的定义及实现,空接口和嵌套接口的概念和使用。

本作品采用《CC 协议》,转载必须注明作者和本文链接