【Go语言】Go语言中的接口类型

2024-06-15 08:20
文章标签 语言 go 接口类型

本文主要是介绍【Go语言】Go语言中的接口类型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Go语言中的接口类型

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

1.接口类型

1.1 接口类型的说明

Go语言中 接口(interface) 是一种抽象的类型。

接口(interface) 是一组 方法 的集合,是 duck-type programming(鸭子类型) 的一种体现,接口所做的事情就像是定义一个协议(规则),只要一台机器有洗衣和甩干的功能,就称之为洗衣机,不关心属性(数据),只关心行为(方法)。

1.2 接口类型的定义

Go语言提倡面向接口编程。

    接口是一个或多个方法签名的集合。任何类型的方法集中只要拥有该接口'对应的全部方法'签名。就表示它 "实现" 了该接口,无须在该类型上显式声明实现了哪个接口。这称为Structural Typing。所谓对应方法,是指有相同名称、参数列表 (不包括参数名) 以及返回值。当然,该类型还可以有其他方法。接口只有方法声明,没有实现,没有数据字段。接口可以匿名嵌入其他接口,或嵌入到结构中。对象赋值给接口时,会发生拷贝,而接口内部存储的是指向这个复制品的指针,既无法修改复制品的状态,也无法获取指针。只有当接口存储的类型和对象都为nil时,接口才等于nil。接口调用不会做receiver的自动转换。接口同样支持匿名字段方法。接口也可实现类似OOP中的多态。空接口可以作为任何类型数据的容器。一个类型可实现多个接口。接口命名习惯以 er 结尾。

每个接口由数个方法组成,接口的定义格式如下:

    type 接口类型名 interface{方法名1( 参数列表1 ) 返回值列表1方法名2( 参数列表2 ) 返回值列表2…}

其中:

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

举个例子:

type writer interface{Write([]byte) error
}

这里定义了一个 writer接口(interface),能够看到的就只是这个接口定义了一个 Write 方法,具体实现什么功能也不可知。

1.3 实现接口的条件

一个对象只要全部实现了接口中的方法,那么就实现了这个接口。换句话说,接口就是一个需要实现的方法列表。

举个例子,这里我们定义一个 Phone 对象

type Phone interface {Call()SendMessage()
}

定义 OPPOHUAWEI 两个结构体:

type OPPO struct {Name  stringPrice float64
}type HUAWEI struct {Name  stringPrice float64
}

Phone 接口中有两个方法 CallSendMessage 方法,因此需要给 OPPOHUAWEI 实现 CallSendMessage 方法就实现了 Phone 接口。

func (oppo OPPO) Call() {fmt.Printf("%s 有打电话的功能 \n", oppo.Name)
}func (oppo OPPO) SendMessage() {fmt.Printf("%s 有发短信的功能 \n", oppo.Name)
}func (huawei HUAWEI) Call() {fmt.Printf("%s 有打电话的功能 \n", huawei.Name)
}func (huawei HUAWEI) SendMessage() {fmt.Printf("%s 有发短信的功能 \n", huawei.Name)
}

接口的实现就是这样,只要实现了接口中的所有方法,就实现了这个接口。

1.4 接口变量类型

接口类型变量能够存储所有实现了该接口的实例。如上 1.3 实现接口的条件 举例所示,Phone 类型的变量能够存储 HUAWEIOPPO 类型的变量。

func interfaceVariable() {// 声明一个Phone 类型的变量xvar x GoInterface.Phone// 实例化一个OPPOfindx6 := GoInterface.OPPO{Name:  "Find X6",Price: 5999,}// 实例化一个HUAWEIp30 := GoInterface.HUAWEI{Name:  "HUAWEI P30",Price: 3999,}// 可以把OPPO实例直接赋值给xx = findx6x.Call()// 可以把HUAWEI实例直接赋值给xx = p30x.Call()
}

2. 类型与接口之间的关系

2.1 一个类型实现多个接口

一个类型可以同时实现多个接口,而接口间彼此独立,不知道对方的实现。 例如,OPPO 手机可以打电话,也可以发短信。我们就分别定义 Caller 接口和 Message 接口,如下:

type Caller interface {Call()
}type Message interface {SendMessage()
}

OPPO 既可以实现 Caller 接口,也可以实现 Message 接口。

type OPPO struct {Name  stringPrice float64
}// 实现Caller接口
func (oppo OPPO) Call() {fmt.Printf("%s支持打电话功能\n", oppo.name)
}// 实现Message接口
func (oppo OPPO) SendMessage() {fmt.Printf("%s支持发短信功能\n", oppo.name)
}func main() {var x Callervar y Messagevar a = OPPO{Name: "Find X6", Price:5999,}x = ay = ax.Call()y.SendMessage()
}

2.2 多个类型实现同一接口

Go语言中不同的类型还可以实现同一接口,首先我们定义一个 Caller 接口,它要求必须由一个 Call 方法。

type Caller interface {Call()
}

例如,HUAWEI 手机可以打电话,OPPO 也可以打电话。

type OPPO struct {Name  stringPrice float64
}type HUAWEI struct {Name  stringPrice float64
}// OPPO 类型实现Caller接口
func (oppo OPPO) Call() {fmt.Printf("%s 有打电话的功能 \n", oppo.Name)
}// HUAWEI 类型实现Caller接口
func (huawei HUAWEI) Call() {fmt.Printf("%s 有打电话的功能 \n", huawei.Name)
}

并且一个接口的方法,不一定需要由一个类型完全实现,接口的方法可以通过在类型中嵌入其他类型或者结构体来实现。

// Phone
type Phone interface {NFC()Call()
}// NFC模块
type NFCER struct{}// 实现Phone接口的NFC()方法
func (nfc NFC) NFC() {fmt.Println("NFC刷卡")
}// OPPO手机
type OPPO struct {NFCER //嵌入NFC模块
}// 实现Phone接口的Call()方法
func (oppo OPPO) Call() {fmt.Println("OPPO手机支持打电话功能")
}

3.空接口

3.1 空接口的定义

空接口是指没有定义任何方法的接口。因此任何类型都实现了空接口。

空接口类型的变量可以存储任意类型的变量。

func emptyInterface() {// 定义一个空接口xvar x interface{}s := "euansu.cn"x = sfmt.Printf("type:%T value:%v\n", x, x)i := 100x = ifmt.Printf("type:%T value:%v\n", x, x)b := truex = bfmt.Printf("type:%T value:%v\n", x, x)
}

3.2 空接口的应用

  • 空接口可以实现接口任意类型的函数参数。

    // 空接口作为函数参数
    func funcMethod(a interface{}) {fmt.Printf("type:%T value:%v\n", a, a)
    }
    
  • 空接口可以作为 map 的值。

    // 空接口作为map值
    var studentInfo = make(map[string]interface{})
    studentInfo["name"] = "李白"
    studentInfo["age"] = 18
    studentInfo["married"] = false
    fmt.Println(studentInfo)
    

参考链接

[1] 接口 https://www.topgoer.com/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/%E6%8E%A5%E5%8F%A3.html

这篇关于【Go语言】Go语言中的接口类型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1062924

相关文章

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

Go 语言中的select语句详解及工作原理

《Go语言中的select语句详解及工作原理》在Go语言中,select语句是用于处理多个通道(channel)操作的一种控制结构,它类似于switch语句,本文给大家介绍Go语言中的select语... 目录Go 语言中的 select 是做什么的基本功能语法工作原理示例示例 1:监听多个通道示例 2:带

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO

go中空接口的具体使用

《go中空接口的具体使用》空接口是一种特殊的接口类型,它不包含任何方法,本文主要介绍了go中空接口的具体使用,具有一定的参考价值,感兴趣的可以了解一下... 目录接口-空接口1. 什么是空接口?2. 如何使用空接口?第一,第二,第三,3. 空接口几个要注意的坑坑1:坑2:坑3:接口-空接口1. 什么是空接

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件