Go语言程序设计(十五)接口

一、接口的概念

        简单地说,Interface是一组Method的组合,可以通过Interface来定义对象的一组行为。如果某个对象实现了某个接口的所有方法,就表示它实现了该“接口”,无须显式地在该类型上添加接口说明。
        假设定义了两个对象Teacher和Student, Teacher实现了方法Reading、Writing和Teaching , Student实现了方法Reading、Writing和Studying。被对象Teacher和Student实现的方法组合就称为Interface。
        例如,Teacher和Student都实现了Interface: Reading 和Writing,也就是说这两个对象是该Interface类型。而对象Student没有实现Interface: Reading、Writing和Teaching,因为它没实现Teaching这个方法。

二、接口的定义

        Interface的定义形式看上去和Struct类似,但是Interface是一个方法的集合,它里面没有其他类型变量,而且Method只用定义原型不用实现。
        Interface要使用关键字“type"和“interface"定义,基本格式如下:

type interfaceName interface{methodName(参数列表)(返回值)methodName(参数列表)(返回值)methodName(参数列表)(返回值)...
}

注意事项:

  • (1)在Go语言中,Interface命名时习惯性以“er”结尾,比如: Printer、Reader、Writer等,即通常以动名词来命名。其他面向对象语言Interface 命名时通常以大写字母“I”开头,比如. NET.Java等。
  • (2)在Go语言中,一个Interface中包含的Method不宜过多,一般0~3个即可。
  • (3)一个Interface可以被任意的对象实现;相同地,一个对象也可以实现多个Interface。

例如:

 三、接口组合

        在Go语言中,除了类型可以匿名组合,接口也可以组合在一起。将一个接口匿名嵌入到另外一个接口中,就是接口组合( Interface combination),这种组合类似于接口的继承( Interface inheritance)。

type SpeakLearner interface{SpeakerLearner
}

        该例中接口SpeakLearner组合了Speaker和Learner两个接口,它既能做Speaker接口的所有事情,又能做Learner接口的所有事情。
        可以认为接口组合是类型匿名组合的一个特殊事例,只不过接口只包含方法,而不包含任何成员变量。

四、空接口

在Go语言中,任何数据类型都默认实现了空Interface,空接口可以这样定义:

interface{}

        空接口也就是包含0个Method的Interface,所以可以使用空接口interface{}定义任意类型变参函数。一个函数把interface{}作为参数,那么它可以接受任意类型的值作为参数,如果一个函数返interface{},就可以返回任意类型的值。
例如:

//函数test1返回1个interface{ }
func test1(a interface{}) {}
//函数test2可返回多个interface{}
func test2(a ... interface{}) {}

        Go语言中的空接口的作用类似于C语言中的void* ,或者Java /C #中的System.Object。

五、接口执行机制

        在Go语言中,接口作为一种引用数据类型,是可被实例化的类型,当定义了一个接口类型变量时,系统将会为其分配内存,并将赋值给它的对象复制存储到该内存区。

接口对象内部由两部分组成:Itab指针和data指针。

struct Iface
{Itab * tab;void * data;
};

        Itab依据data类型创建,存储了接口动态调用的元数据信息,其中包括data类型所有符合接口签名的方法地址列表。使用接口对象调用方法时,就从Itab中查找所对应的方法,并将*data(指针)作为Receiver参数传递给该方法,从而完成实际目标方法调用。
        而编译器在构建Itab时,会区分T和* T方法集(Method sets) ,并从中获取接口实现方法的地址指针。接口调用不会做Receiver自动转换,目标方法必须在接口实现的方法集中。

接口方法集规则如下:
(1) T仅拥有属于T类型的方法集,而*T则同时拥有(T+ * T)方法集。
(2)基于T实现方法,表示同时实现了interface( T)和interface(* T)接口。
(3)基于*T实现方法,那就只能是对interface(*T)实现接口。

六、接口的赋值

        与其他面向对象语言不同,Go语言中的接口还可以赋值,如果定义了一个Interface的变量,那么这个变量里面可以存储实现这个Interface的任意类型的对象。
        例如上面例子中,如果定义了一个Speaker接口类型的变量is,那么is里面就可以存储对象People、Teacher或者Student的值。
        因为接口类型is 能够同时持有这三种类型的对象,所以可以定义一个包含Speaker接口类型元素的Slice,这个Slice可以被赋予实现了Speaker接口的任意结构的对象,这个和传统意义上面的Slice有所不同。

 编译并运行该程序,输出结果为:

Hi,I'm张三,Nice to meet you!
Hi,my name is郑智,I'm work ing in Computer Science.
Hi,my name is李明,I'm studing in Yale University.
I'm learning Golang in Yale University.

七、接口类型推断

        通过接口的赋值可知,接口类型变量里面可以存储任意类型的数值(该类型实现了Interface)。那么如何反向知道接口类型变量里面实际保存的是哪一种类型的对象呢?这就是接口类型推断。
        利用接口类型推断,可以判断接口对象是否是某个具体的接口或者类型。在Go语言中,目前有两种常用的方法可以进行接口类型推断:Comma-ok断言和Switch测试。

1、Comma-ok断言

使用Comma-ok断言可以进行接口类型查询,格式如下:

value, ok= element.(T)

        上式中value是变量的值,ok是bool类型,element是接口类型变量,T是断言的类型。如果element里面确实存储了T类型的数值,那么ok返回true,否则返回false。

2、Switch测试

        除了使用Commaok断言,还可以使用Switch测试推断接口类型,而且程序结构更简洁,格式如下:

switch value := element.(type){case int:case string:...
}

        需要强调的是:element.(type)语法不能在Switch语句外的任何逻辑语句里面使用,如果要在Switch外面判断一个类型就要使用Comma-ok断言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/15484.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

qt信号与槽

信号与槽的概念: 1>信号:信号就是信号函数,可以是组件自身提供,也可以是用户自己定义,自定义时,需要类体的signals权限下进行定义,该函数是一个不完整的函数,只有声明&#xff0…

【FFMPEG】AVFilter使用流程

流程图 核心类 AVFilterGraph ⽤于统合这整个滤波过程的结构体 AVFilter 滤波器,滤波器的实现是通过AVFilter以及位于其下的结构体/函数来维护的 AVFilterContext ⼀个滤波器实例,即使是同⼀个滤波器,但是在进⾏实际的滤波时,也…

【已解决】Couldn‘t find a tree builder with the features you requested: lxml

这是一个常见于Python爬虫代码的报错。 报错代码: soup BeautifulSoup(r.text, xml) 报错原因: BeautifulSoup的解析方法之一,xml,需要安装好lxml库才行 解决办法: 安装 lxml 库即可。 pip install lxml 安装好…

【私有云】网络虚拟化

前言 大家好,我是秋意零。 之前一直对 OpenStack 网络很陌生与神奇啊,不知道它是如何实现的,网络结构是怎样的。不过,今天介绍的是网络虚拟化,它在 OpenStack 中及云计算中是非常重要的概念,是理解 OpenS…

Basic of Solidity (solidity基础)

目录 1.first contract 申明编译器版本 定义合约 合约构造函数 定义变量 定义函数 2.data type 值类型(Value Types) 引用类型(Reference Types) 映射类型(Mapping Types) Solidity是一种用于编写…

接口性能优化技巧

背景 我负责的系统在去年初就完成了功能上的建设,然后开始进入到推广阶段。随着推广的逐步深入,收到了很多好评的同时也收到了很多对性能的吐槽。 刚刚收到吐槽的时候,我们的心情是这样的: 当越来越多对性能的吐槽反馈到我们这里的…

智安网络|网络安全威胁多样化和复杂化,防护任务日益艰巨

随着数字化和网络化的加速发展,人们面临的网络安全问题日益增多。由于网络安全威胁的多样性和复杂性,网络安全防护变得越来越困难。 一. 网络安全威胁的复杂性 网络安全威胁种类繁多,主要包括病毒、木马、蠕虫、间谍软件、恶意软件、黑客攻击…

基于单片机指纹考勤系统的设计与实现

功能介绍 以51单片机作为主控系统;利用指纹采集模块存储打卡信息;12864显示当前考勤信息,时间 ;如果迟到 语音播报 您已迟到;按键进行注册指纹、删除指纹、设置当前时间和签到时间、查询打卡等;具有掉电保存…

把同组人做的工作写在自己简历上,算造假吗?知道这个需求不是我做的人,这个世界可能不超过10个人!...

把同组人做的东西写在自己简历上,算造假吗? 一位网友问: 同组人做的需求,需求细节我完全可以讲得清楚。知道这个需求不是我做的人,全世界可能不超过10个人,我把这个需求写在自己简历上算简历造假吗&#xf…

【Python爬虫与数据分析】时间、日期、随机数标准库

目录 一、模块化概述 二、time库 1. 时间获取 2. 时间格式化 3. 程序计时 三、datetime库 1. datetime.datetime类 2. datetime.timedelta类 四、random库 1. 基本随机函数 2. 扩展随机函数 3. 随机时间的生成 一、模块化概述 Python程序由模块组成,一个…

Mysql中默认自动事务autocommit关闭和开启方式、rollback回滚恢复数据的使用方法

文章目录 autocommit自动提交事物一、查看autocommit状态二、修改autocommit 状态的方式1、第一种方式2、修改mysql配置文件my.cnf 二、rollback回滚1、autocommit 开启1、autocommit 关闭 autocommit自动提交事物 MySQL 默认开启事务自动提交模式,每条 SOL 语句都…

超详细 | 遗传-粒子群自适应优化算法及其实现(Matlab)

作者在前面的文章中介绍了两种经典的优化算法——遗传算法(GA)和粒子群算法(PSO),这些智能优化算法解决问题的方式和角度各不相同,都有各自的适用域和局限性,对智能优化算法自身做的改进在算法性能方面得到了一定程度的提升,但算法…