Go基础编程 - 10- 接口(interface)

接口(interface)

  • 1. 接口
    • 1.1. 接口的定义
    • 1.2. 接口的实现
    • 1.3. 接口的变量类型
    • 1.4. 值接收者和指针接收者实现接口的区别
      • 1.4.1. 值接收者实现接口
      • 1.4.2. 指针接收者实现接口
  • 2. 类型与接口的关系
  • 3. 接口的嵌套
  • 4. 空接口
    • 4.1. 空接口的应用

上一篇:通道(Channel)
下一篇:函数(func)


1. 接口

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

1.1. 接口的定义

Go语言提倡面向接口编程。每个 interface 都有一组方法,这些方法定义了接口的行为。

type 接口名 interface {方法名1(参数列表) 返回值列表方法名2(参数列表) 返回值列表...
}// 1.接口名:使用type将接口定义为自定义的类型名。Go语言接口命名习惯以`er`结尾。接口名最好要能突出该接口的类型含义。
// 2.方法名:方法名首字母大写且这个接口类型名首字母也是大写时,该方法可以被接口所在的包(package)之外的代码访问。
// 3.参数列表、返回值列表中的参数变量名可以省略。
  • 接口是一个或多个方法签名的集合
  • 接口只有方法声明,没有实现,没有数据字段
  • 对象赋值给接口时,会发生拷贝,而接口内部存储的是指向这个复制品的指针,既无法修改复制品的状态,也无法获取指针。
  • 接口同样支持匿名字段方法
  • 接口可以匿名嵌入其它接口,或嵌入到结构中
  • 接口调用不会做receiver的自动切换
  • 接口也可实现类似OOP中的多态
  • 空接口可以作为任何类型数据的容器
  • 一个类型可以实现多个接口

1.2. 接口的实现

任何类型的方法集中只要全部“实现”了接口中的方法,就表示它“实现”了该接口,无须在该类型上显式声明实现了哪个接口。

定义一个Sayer接口

type Sayer interface {Speak()
}

定义一个Person类型,并实现了Speak方法,该类型实现了Sayer接口。

type Person struct {Name string
}func (p Person) Speak() {fmt.Println("Hello, my name is", p.Name)
}

1.3. 接口的变量类型

接口类型变量能够存储所有实现了该接口的实例。

例如:

package mainimport "fmt"type Sayer interface {Speak()
}type Person struct {Name string
}func (p Person) Speak() {fmt.Println("Hello, my name is", p.Name)
}func (p Person) Run() {fmt.Println("跑步去了...")
}func main() {var s Sayerp := Person{"小强"}s = p   // 接口类型变量可以存储实现了该接口的实例s.Speak() // Hello, my name is 小强p.Run()//s.Run() // 但不可使用接口外的方法,报错:s.Run undefined (type Sayer has no field or method Run)
}

1.4. 值接收者和指针接收者实现接口的区别

Go语言指针语法糖:当我们使用指针调用一个方法或访问结构体的字段时,编译器会自动解引用指针,这使得我们可以像直接访问变量一样操作指针。

结构体中,值方法集合不包括指针方法,指针方法集合包括所有方法

1.4.1. 值接收者实现接口

type Sayer interface {Speak()
}type Person struct {Name string
}func (p Person) Speak() {fmt.Println("Hello, my name is", p.Name)
}func main() {var s Sayerp := Person{"小强"}s = pp2 := &Person{"梦想家"}s = p2s.Speak()
}

从上面的代码中我们可以发现,使用值接收者实现接口之后,不管是Person结构体类型的变量p,还是*Person结构体指针类型的变量p2,都可以赋值给该接口变量s。因为Go语言中有对指针类型变量求值的语法糖,p2内部会自动求值*p2。

1.4.2. 指针接收者实现接口

func (p *Person) Speak() {fmt.Println("Hello, my name is", p.Name)
}func main() {var s Sayerp := Person{"小强"}// Person的方法集合,不包括指针方法,因此Person类型实例并未实现Speak方法,也就未实现Sayer接口。s = p	// 报错: cannot use p (variable of type Person) as type Sayer in assignment:// Person does not implement Sayer (Speak method has pointer receiver)p2 := &Person{"梦想家"}s = p2s.Speak()
}

此时实现Speak接口的是*Person类型,所以不能给s传入Person类型的p,此时s只能存储*Person类型的值。

2. 类型与接口的关系

一个类型可以同时实现多个接口,而接口之间彼此独立,不知道对方的实现。

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

// WashingMachine 洗衣机
type WashingMachine interface {wash()dry()
}// 甩干器
type dryer struct{}// 实现WashingMachine接口的dry()方法
func (d dryer) dry() {fmt.Println("甩一甩")
}// 海尔洗衣机
type haier struct {dryer //嵌入甩干器,实现接口dry方法
}// 实现WashingMachine接口的wash()方法
func (h haier) wash() {fmt.Println("洗刷刷")
}

3. 接口的嵌套

接口与接口间可以通过嵌套生成新的接口。嵌套得到的接口的使用与普通接口一样。

// Sayer 接口
type Sayer interface {say()
}// Mover 接口
type Mover interface {move()
}// 接口嵌套
type animal interface {SayerMover
}

4. 空接口

空接口是指没有定义任何方法的接口。因此任何类型都实现了空接口,空接口类型的变量可以存储任意类型的变量。

func main() {var x interface{}s := "string"x = si := 100x = ib := truex = b
}

4.1. 空接口的应用

空接口作为函数的参数(或返回值),实现可以接收任意类型的函数参数(或返回值)

func foo(arg interface{}) {fmt.Printf("type:%T,  value:%v\n", arg, arg)
}func main() {foo(1)foo("hello")foo(true)foo(nil)foo(map[string]int{"a": 1})
}

空接口作为map的值,实现可以保存任意值的字典

func main() {var m map[string]interface{}m["name"] = "小强"m["age"] = 18m["married"] = falsefmt.Println(m)
}

使用类型断言,获取接口的值
空接口可以存储任意类型的值,获取其存储的具体的值就可以使用类型断言,其语法格式:
【参考基本类型章节:3.4 类型断言】

v, ok := x.(T)
// x:表示类型为interface{}的变量
// T:表示断言x可能的类型
// v:接口值
// ok:布尔值,true表示断言成功,false表示断言失败。可省略,省略后断言失败则产生panic。func main() {var x interface{}x = "hello"v, ok := x.(string)if ok {fmt.Println(v)} else {fmt.Println("类型断言失败")}
}

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

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

相关文章

docker基础镜像

一、配置 docker 本地源 [docker-ce-stable] nameDocker CE Stable baseurlhttp://10.35.186.181/docker-ce-stable/ enabled1 gpgcheck0 配置阿里云Docker Yum源 yum install -y yum-utils device-mapper-persistent-data lvm2 git yum-config-manager --add-repo http://mirr…

探索PyCharm的调试技巧:深入变量的神秘世界

探索PyCharm的调试技巧:深入变量的神秘世界 在软件开发的过程中,调试是不可或缺的一部分。它帮助开发者理解代码的执行流程,查找并修复错误。PyCharm,作为一款功能强大的IDE,提供了一整套调试工具,让我们能…

动态数据下的稳定器:在线学习在目标检测中的适应之道

动态数据下的稳定器:在线学习在目标检测中的适应之道 在线学习(Online Learning)是一种灵活的机器学习范式,它允许模型通过连续学习新样本来适应数据分布的变化。这对于目标检测系统来说至关重要,因为它们需要在不断变…

Windows安装Visual Studio2022 + QT5.15开发环境

最近,把系统换成了Windows11,想重新安装QT5.12,结果发现下载不了离线安装包。 最后索性安装QT5.15了,特此记录下。 预祝大家:不论是何时安装,都可以安装到指定版本的QT。 一、VS2022安装 VS2022官网下…

ubuntu 22.04 安装部署gitlab详细过程

目录 gitlab介绍 gitlab安装 步骤1:更新系统 步骤2:添加 GitLab 的 GPG 密钥 gitlab企业版 gitlab社区版 步骤3:安装 GitLab 社区版 社区版 步骤4:初始化 GitLab 步骤5:访问 GitLab 步骤6:查看r…

C++ - 基于多设计模式下的同步异步⽇志系统

1.项目介绍 项⽬介绍 本项⽬主要实现⼀个⽇志系统, 其主要⽀持以下功能: • ⽀持多级别⽇志消息 • ⽀持同步⽇志和异步⽇志 • ⽀持可靠写⼊⽇志到控制台、⽂件以及滚动⽂件中 • ⽀持多线程程序并发写⽇志 • ⽀持扩展不同的⽇志落地⽬标地 2.开发环境 • Cent…

【专家系统】系统地掌握专家系统的基本概念、技术原理、实现方法以及应用实践。

一、基础概念与理论 专家系统基础 定义:专家系统是一种人工智能程序,它利用专家知识和推理能力来解决特定领域中的复杂问题。特点:具有专业知识、可解释性和可靠性。组成部分: 知识库:存储特定领域的专家知识&#x…

AI学习记录 - 导数在神经网络训练中的作用(自己画的图,很丑不要介意!)

导数的作用 我们去调整神经网络的权重,一般不会手动去调整,如果只有很少的神经元,人工调整确实可以实现,当我们有几十层,一层几百上千个神经元的时候,人工调整就不可能了。 一个权重的调整涉及到两个问题&…

TCP的FIN报文可否携带数据

问题发现: 发现FTP-DATA数据传输完,TCP的挥手似乎只有两次 实际发现FTP-DATA报文中,TCP层flags中携带了FIN标志 piggyback FIN 问题转化为 TCP packet中如果有FIN flag,该报文还能携带data数据么? 答案是肯定的 RFC7…

Go协程的运行机制以及并发模型

进程与线程 进程与线程都是os用来运行程序的基本单元。其中进程是正在执行的程序的实例,它包含了程序代码、数据、文件和系统资源等。进程是os资源分配的基本单元,每个进程都有自己独立的地址空间、文件描述符、网络连接、进程ID等系统资源。进程与进程…

【LeetCode:3098. 求出所有子序列的能量和 + 记忆化缓存】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第四十七章 字符设备和杂项设备总结回顾

i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

connect-multiparty中间件用法以及实例--文件上传中间件(保姆级别教学)

connect-multiparty中间件的用法包括安装和引入、基本设置、路由应用、文件处理以及安全和优化等步骤。 connect-multiparty是一个专为Connect和Express框架设计的文件上传中间件,它基于multiparty库,用于处理多部分表单数据,尤其针对文件上传…

pytorch中的zero_grad()执行时机

在反向传播(backward())前执行即可 zero_grad() 用以清除优化器的梯度对张量执行backward(),以计算累积梯度执行optimizer.step(),优化器使用梯度更新参数当优化器更新完成,梯度即失去意义,即可以清除,为保证下一次梯度开始累积时为0,则在下一次执行反向传播前清除即可

sqlalchemy使用json_unquote函数的mysql like查询

sqlalchemy使用json_unquote函数的mysql like查询 在SQLAlchemy中使用json_unquote函数查询MySQL JSON字段可以通过使用func函数来实现。下面是一个示例,假设有一个名为users的表,其中包含一个名为data的JSON字段,我们想要查询该字段的内容: from sqlalchemy import crea…

Redis核心技术与实战学习笔记

Redis核心技术与实战学习笔记 最近想沉下心来看下redis,买了蒋德钧老师的《Redis 核心技术与实战》,这里记录一些学习笔记 希望能够坚持下去有想一起学习的童鞋,可以点击跳转到文章尾部获取学习资源,仅供学习不要用于任何商业用途!!! redis知识全景图 …

前端JS特效第50集:zyupload图片上传

zyupload图片上传,先来看看效果: 部分核心的代码如下(全部代码在文章末尾): var operimg_id; var zoom_rate100; var zoom_timeout; function rotateimg(){var smallImg$("#"operimg_id);var numsmallImg.attr(curr_rotate);if(nu…

ESP8266用AT指令实现连接MQTT

1准备工作 硬件(ESP8266)连接电脑 硬件已经烧入了MQTT透传固件 2实现连接 2-1(进入AT模式) 打开串口助手发送如下指令 AT 2-2(复位) ATRST 2-3(开启DHCP,自动获取IP&#x…

免费视频批量横版转竖版

简介 视频处理器 v1.3 是一款由是貔貅呀开发的视频编辑和处理工具,提供高效便捷的视频批量横转竖,主要功能: 导入与删除文件:轻松导入多个视频文件,删除不必要的文件。暂停与继续处理:随时暂停和继续处理。…

C# Math.Ceiling方法向上取整和Math.Floor方法向下取整

Math.Ceiling方法向上取整 用于对指定的双精度浮点值进行向上取整。这意味着它会返回大于或等于指定数字的最小整数。如果数字是整数,则Math.Ceiling将返回该整数本身。 double number1 3.13; double number2 5.0; double number3 -2.72;double result1 Math.…