Golang笔记——Interface类型
大家好,这里是,关注 公主号:Goodnote,专栏文章私信限时Free。本文详细介绍Golang的interface数据结构类型,包括基本实现和使用等。

文章目录
- Go 语言中的 `interface` 详解
- 接口定义
- 实现接口
- 空接口 `interface{}`
- 示例:空接口的使用
- interface 类型判断
- 1. 类型断言(Type Assertion)
- 语法
- 示例
- 类型转换和类型断言的区别
- 2. 类型开关(Type Switch)
- 语法
- 示例
- 3. 反射(Reflection)
- 示例
- 反射的关键点
- 总结
- 接口与多态
- 解释
- 接口的嵌套
- 示例
- 总结
- 历史文章
- MySQL数据库
- Redis
- Golang
Go 语言中的 interface 详解
Go 语言中的 interface 是一种强大且灵活的类型系统机制,它使得 Go 能够实现类似面向对象语言多态的特性。接口是一组方法签名的集合,而接口类型定义了某些行为,任何类型只要实现了接口中的方法,就自动成为该接口的实现类型。
简单的说,interface主要表现在以下几个方面:
- 方法的集合:接口是方法的集合,定义了一个类型需要实现哪些方法,但不关心实现的具体细节。只要一个类型实现了接口中的方法,就被认为实现了这个接口。
- 多态实现:接口的核心作用之一是实现多态。在 Go 中,不同类型只要实现了相同的接口方法,就可以通过接口来统一处理,达到灵活的多态性。这使得我们可以编写更加解耦和可扩展的代码。
- 空接口
interface{}是一种变量类型:接口是 Go 中的一个类型,空接口(interface{}) 是最基础的接口类型,它可以存储任何类型的值。实际上它是一个由两部分组成的结构体:- 类型(Dynamic Type):接口变量所保存值的具体类型。
- 值(Dynamic Value):接口变量所保存的具体值。
在 Go 中,接口是非常核心的概念,它帮助我们编写解耦、灵活、可扩展的代码。
接口定义
接口定义了类型应该具备的行为(即方法)。Go 的接口与其他语言(如 Java 或 C++)中的接口有一些不同之处,特别是Go 的接口不需要显式声明实现,即只要类型实现了接口的方法,就自动实现了该接口。
type InterfaceName interface {Method1() // 方法签名Method2() // 方法签名
}
实现接口
Go 不要求显式声明某个类型实现了一个接口,只要该类型实现了接口中声明的所有方法,它就自然地“实现”了该接口。接口与类型之间的关系是隐式的。
package mainimport "fmt"// 定义接口
type Speaker interface {Speak() // 定义接口中的方法
}// 定义结构体
type Person struct {Name string
}// Person 实现了 Speaker 接口的 Speak 方法
func (p Person) Speak() {fmt.Println("Hello, my name is", p.Name)
}func main() {// 创建 Person 类型的实例p := Person{Name: "Alice"}// 将 p 赋给接口类型 Speakervar speaker Speaker = p// 调用接口的方法speaker.Speak() // 输出:Hello, my name is Alice
}
说明:
Speaker接口有一个方法Speak。Person类型实现了Speak方法,因此它自动实现了Speaker接口。- 在
main函数中,p被赋给了接口类型Speaker,然后调用接口的方法Speak。
空接口 interface{}
空接口 interface{} 是一个特殊的接口类型,它没有定义任何方法。由于任何类型都实现了空接口。空接口通常用于存储任何类型的值,类似于其他语言中的 Object 类型。
示例:空接口的使用
package mainimport "fmt"func main() {var x interface{} // 声明一个空接口x = 42 // x 可以存储 intfmt.Println(x) // 输出:42x = "Hello" // x 可以存储 stringfmt.Println(x) // 输出:Hellox = 3.14 // x 可以存储 float64fmt.Println(x) // 输出:3.14
}
interface 类型判断
在 Go 中,由于接口类型是通用的,它可以存储任何实现了该接口的类型,因此在使用接口时,可能并不知道它具体存储的是哪个类型的值。为了处理这种不确定性,Go 提供了三种常用的机制来检测或转换接口的实际类型:
- 类型断言(Type Assertion)
- 类型开关(Type Switch)
- 反射(Reflection)
这三者在 Go 中各有不同的用途,适用于不同的场景。通常情况下,如果你只需要判断一个接口的类型并进行相应处理,类型断言 或 类型开关 是更常见的选择;而 反射 则通常用于更加动态和通用的场景,例如实现框架、库、ORM 等。
下面分别详细介绍这三种机制:
1. 类型断言(Type Assertion)
类型断言用于从接口类型转换回具体类型。它允许我们在运行时检查接口值的动态类型,并进行转换。
语法
value, ok := x.(T)
x是接口类型的变量,T是你想要转换成的具体类型。- 如果
x存储的值是T类型,value将会是存储的值,而ok为true。 - 如果
x存储的值不是T类型,value会是T类型的零值,而ok为false。
示例
package mainimport "fmt"func main() {var a interface{} = 42// 类型断言if v, ok := a.(int); ok {fmt.Println("a is an int:", v)} else {fmt.Println("a is not an int")}
}
输出:
a is an int: 42
类型转换和类型断言的区别
- 类型转换 是编译时的操作,用于在兼容类型之间进行显式转换。它适用于基本类型之间以及自定义类型的转换。
- 类型断言 是运行时的操作,用于从接口类型中提取具体的类型和值。它适用于动态类型判断的场景。
属性
类型转换 (Type Conversion)
类型断言 (Type Assertion)
使用场景
在兼容的类型之间进行显式转换(如 int 转 float64)。
用于从接口类型中提取底层的具体类型和值。
操作时机
编译时。
运行时。
适用范围
基本数据类型、自定义类型等。
接口类型(interface{} 或其他接口)。
结果
将值转换为目标类型。
提取接口的具体值或判断类型是否匹配。
错误处理
不兼容类型转换会导致编译错误。
不安全断言会导致运行时 panic;安全断言返回一个布尔值。
语法
value := T(originalValue)
value, ok := iface.(T) 或 value := iface.(T)
2. 类型开关(Type Switch)
类型开关是 Go 中提供的更强大、更灵活的机制,它允许我们对接口值的类型进行多分支判断。与普通的 switch 语句不同,类型开关的 case 中是基于接口的动态类型进行匹配的。
语法
switch v := x.(type) {
case T1:// x 是 T1 类型
case T2:// x 是 T2 类型
default:// x 是其他类型
}
x.(type)会检查x接口的动态类型。- 你可以根据不同的类型执行不同的逻辑。
示例
package mainimport "fmt"func identifyType(x interface{}) {switch v := x.(type) {case int:fmt.Println("int:", v)case string:fmt.Println("string:", v)default:fmt.Println("unknown type")}
}func main() {identifyType(42) // 输出:int: 42identifyType("hello") // 输出:string: helloidentifyType(3.14) // 输出:unknown type
}
3. 反射(Reflection)
Go 的 reflect 包提供了在运行时操作接口的功能,能够动态地获取接口的具体类型和方法。这是 Go 中非常强大的特性,可以在不知道类型的情况下执行一些操作,例如获取类型的名称、字段信息、调用方法等。
示例
package mainimport ("fmt""reflect"
)type Dog struct{}func (d Dog) Speak() {fmt.Println("Woof!")
}func main() {var a interface{} = Dog{}// 使用反射获取类型t := reflect.TypeOf(a)fmt.Println("Type:", t)// 使用反射获取值v := reflect.ValueOf(a)fmt.Println("Value:", v)// 通过反射调用方法if t.Kind() == reflect.Struct {method := v.MethodByName("Speak")if method.IsValid() {method.Call(nil) // 输出:Woof!}}
}
反射的关键点
reflect.TypeOf()用来获取接口的具体类型。reflect.ValueOf()用来获取接口的具体值。reflect.ValueOf(a).MethodByName("MethodName")可以动态调用结构体的方法。
总结
- 类型断言:用于在运行时提取接口的具体类型值,如果类型不匹配,可以使用
ok变量避免运行时错误。 - 类型开关:允许你对接口值的动态类型进行多分支判断,可以在多个可能的类型之间选择。
- 反射:通过
reflect包可以在运行时获取接口的类型和值,甚至可以动态地调用方法或修改值。
接口与多态
Go 语言的多态是通过接口实现的。接口提供了一种方法,让不同类型的对象能以统一的方式来调用它们的行为。
package mainimport "fmt"type Animals interface {Say()
}type Dog struct{}
type Cat struct{}func (d Dog) Say() {fmt.Println("wangwang")
}func (c Cat) Say() {fmt.Println("miaomiao")
}func main() {var d Dogd.Say() // 输出:wangwangvar c Catc.Say() // 输出:miaomiao// 使用接口变量1,可以接受任何实现了 Say() 方法的类型var a Animalsa = da.Say() // 输出:wangwanga = ca.Say() // 输出:miaomiao// 使用接口变量2,可以接受任何实现了 Say() 方法的类型var a1 Animalsa1 = Dog{}a1.Say() // 输出:wangwanga1 = Cat{}a1.Say() // 输出:miaomiao
}
解释
Dog和Cat都实现了Animals接口。a是一个接口类型,可以存储任何实现了Say方法的类型。- 通过多态,我们可以使用同一个接口变量
a存储不同的类型,并调用它们各自的Say方法。
接口的嵌套
Go 允许接口嵌套,接口可以继承其他接口的方法。当一个接口嵌套另一个接口时,它自动包含了被嵌套接口的方法。
示例
package mainimport "fmt"// 定义 Animal 接口
type Animal interface {Speak()
}// 定义 Worker 接口,嵌入 Animal 接口
type Worker interface {Animal // Animal 接口被嵌套在 Worker 接口中Work()
}// 定义 Dog 结构体
type Dog struct{}// Dog 实现了 Animal 接口的 Speak 方法
func (d Dog) Speak() {fmt.Println("wangwang")
}// Dog 实现了 Worker 接口的 Work 方法
func (d Dog) Work() {fmt.Println("Dog is working!")
}func main() {// 创建 Dog 类型的对象var w Worker = Dog{}// 调用 Worker 接口的方法w.Speak() // 输出:wangwangw.Work() // 输出:Dog is working!
}
-
接口嵌套:
Worker接口通过Animal接口嵌套了Speak方法,这意味着Worker接口需要实现Speak和Work方法。 -
Dog 类型实现接口:
Dog类型实现了Speak和Work方法,满足了Worker接口的要求。 -
接口引用:在
main函数中,w是Worker类型的接口变量,它引用了Dog类型的对象。由于Dog类型实现了Speak和Work方法,所以可以调用w.Speak()和w.Work()。
总结
- Go 中的接口:接口是一组方法签名的集合,Go 语言通过接口实现了多态。
- 隐式实现:Go 中不需要显式声明类型实现接口,任何实现了接口方法的类型都会自动实现该接口。
- 空接口:
interface{}可以存储任何类型的值,类似于其他语言中的Object类型。 - 类型断言:允许从接口类型转换回具体类型,提供灵活的运行时类型检查。
- 接口与多态:通过接口,Go 实现了动态多态,允许不同类型通过统一的接口调用各自的行为。
接口是 Go 语言的核心特性之一,它使得 Go 在保持简洁和灵活性的同时,支持面向对象的编程风格。
历史文章
MySQL数据库
MySQL数据库
Redis
Redis数据库笔记合集
Golang
- Golang笔记——语言基础知识
- Golang笔记——切片与数组
- Golang笔记——hashmap
- Golang笔记——rune和byte
- Golang笔记——channel
相关文章:
Golang笔记——Interface类型
大家好,这里是,关注 公主号:Goodnote,专栏文章私信限时Free。本文详细介绍Golang的interface数据结构类型,包括基本实现和使用等。 文章目录 Go 语言中的 interface 详解接口定义实现接口空接口 interface{} 示例&…...
如何查看图片的原始格式
问题描述:请求接口的时候,图片base64接口报错,使用图片url请求正常 排查发现是图片格式的问题: 扩展名可能被篡改:如果文件损坏或扩展名被手动修改,实际格式可能与显示的不同,需用专业工具验证…...
FreiHAND (handposeX-json 格式)数据集-release >> DataBall
FreiHAND (handposeX-json 格式)数据集-release 注意: 1)为了方便使用,按照 handposeX json 自定义格式存储 2)使用常见依赖库进行调用,降低数据集使用难度。 3)部分数据集获取请加入:DataBall-X数据球(free) 4)完…...
【Rust中级教程】2.8. API设计原则之灵活性(flexible) Pt.4:显式析构函数的问题及3种解决方案
喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 说句题外话,这篇文章一共5721个字,是我截至目前写的最长的一篇文章&a…...
LabVIEW Browser.vi 库说明
browser.llb 库位于C:\Program Files (x86)\National Instruments\LabVIEW 2019\vi.lib\Platform目录,它是 LabVIEW 平台下用于与网络浏览器相关操作的重要库。该库为 LabVIEW 开发者提供了一系列工具,用于实现网页浏览控制、网页数据获取与交互等功能&a…...
promise的方法有哪些?【JavaScript】
Promise对象在JavaScript中是一种处理异步操作的方式,它提供了一组方法来管理和控制异步操作的结果。以下是一些常用的Promise方法: 以下是对 constructor(executor)、then(onFulfilled, onRejected)、catch(onRejected)、 finally(onFin…...
基于模仿学习(IL)的端到端自动驾驶发展路径
基于模仿学习(IL)的端到端自动驾驶发展路径 1. 核心论文解析 (1) UniAD:感知-规划一体化 核心思想:首次提出将感知任务(如目标检测、车道线识别、轨迹预测)与规划任务集成到统一的端到端框架中ÿ…...
第1篇:SOLR 简介与源码环境搭建
第1篇:SOLR 简介与源码环境搭建 1.1 SOLR 是什么? Apache SOLR 是一个基于 Apache Lucene 的高性能开源搜索平台。它不仅继承了 Lucene 强大的全文搜索能力,还通过封装和扩展,提供了企业级的功能,比如分布式搜索(SolrCloud)、RESTful API、动态 Schema 管理等。自 200…...
Docker 搭建 Redis 数据库
Docker 搭建 Redis 数据库 前言一、准备工作二、创建 Redis 容器的目录结构三、启动 Redis 容器1. 通过 redis.conf 配置文件设置密码2. 通过 Docker 命令中的 requirepass 参数设置密码 四、Host 网络模式与 Port 映射模式五、检查 Redis 容器状态六、访问 Redis 服务总结 前言…...
MySQL 连表查询:原理、语法与优化
目录 引言 什么是连表查询? 连表查询的类型 1. 内连接(INNER JOIN) 2. 左连接(LEFT JOIN) 3. 右连接(RIGHT JOIN) 4. 全连接(FULL JOIN) 5. 交叉连接(…...
实战技巧:如何快速提高网站收录的权威性?
快速提高网站收录的权威性是一个系统性的工作,涉及内容质量、网站结构、外部链接、用户体验等多个方面。以下是一些实战技巧,可以帮助你快速提升网站收录的权威性: 一、提升内容质量 原创性: 确保网站内容具备高质量与原创性&a…...
vue语法v-model例子单选题和多选题
<template><!-- 单选框 --><input type"radio" v-model"danxuan" value"a"><label for"a">a</label><input type"radio" v-model"danxuan" value"b"><label fo…...
计算机网络面试知识点总结
目录 1. 计算机网络的基本知识点2. OSI 七层模型3. TCP/IP 四层模型4. TCP 和 UDP4.1 TCP 协议4.2 TCP 流量控制4.3 TCP 拥塞控制4.4 TCP 三次握手4.5 TCP 四次挥手4.6 TCP 粘包问题4.7 TCP Socket交互流程4.8 UDP 协议以及和 TCP 协议的不同 5. HTTP协议5.1 HTTP 请求方法以及…...
JVM生产环境问题定位与解决实战(二):JConsole、VisualVM到MAT的高级应用
生产问题定位指南:几款必备的可视化工具 引言 在上一篇文章中,详细的介绍了JDK自带的一系列命令行工具,,如jps、jmap、jstat、jstack以及jcmd等,这些工具为排查和诊断Java虚拟机(JVM)问题提供…...
c++入门-------命名空间、缺省参数、函数重载
C系列 文章目录 C系列前言一、命名空间二、缺省参数2.1、缺省参数概念2.2、 缺省参数分类2.2.1、全缺省参数2.2.2、半缺省参数 2.3、缺省参数的特点 三、函数重载3.1、函数重载概念3.2、构成函数重载的条件3.2.1、参数类型不同3.2.2、参数个数不同3.2.3、参数类型顺序不同 前言…...
Lua语言入门(自用)
全局与非全局 在lua语言当中没有被local表示的是全局变量 反之则是本地变量(仅仅作用在某个文件,函数,或者代码块) 下面是实例代码和运行结果 --hello.luaA 10;--这样就是全局变量,然后这个编译器如果是大写就是默认的全局变量 local b 3;--这样就是局部变量--reference.…...
大数据开发平台的框架
根据你的需求,以下是从 GitHub 推荐的 10 个可以实现大数据开发平台的项目: 1. Apache Spark Apache Spark 是一个开源的分布式计算框架,适用于大规模数据处理和分析。它提供了强大的数据处理能力,支持实时数据处理、机器学习和…...
X86_64位下的GS寄存器
在 64 位模式下,段机制通常(但不是完全)被禁用,从而创建一个平坦的 64 位线性地址空间。处理器将 CS、DS、ES、SS 的段基地址视为零,从而创建一个与有效地址相等的线性地址。FS 和 GS 段是例外。这些段寄存器ÿ…...
#6【TIP2023】Dif-Fusion
📜 Dif-Fusion: Toward High Color Fidelity in Infrared and Visible Image Fusion With Diffusion Models 🍸 源码:https://github.com/GeoVectorMatrix/Dif-Fusion 🍺 前向扩散过程 前向过程看成是逐步加噪的Markov链,在每一个时间步 t t t ,...
科普:“git“与“github“
Git与GitHub的关系可以理解为:Git是一种软件工具,而GitHub则是一个在线平台,它们是“一家子”。二者的关联最直接体现在你通过Git在GitHub仓库中clone软件包到你的机器中来。 具体来说: 一、Git 定义:Git是一个开源的…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程
鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...
数据库——redis
一、Redis 介绍 1. 概述 Redis(Remote Dictionary Server)是一个开源的、高性能的内存键值数据库系统,具有以下核心特点: 内存存储架构:数据主要存储在内存中,提供微秒级的读写响应 多数据结构支持&…...
轻量级Docker管理工具Docker Switchboard
简介 什么是 Docker Switchboard ? Docker Switchboard 是一个轻量级的 Web 应用程序,用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器,使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...
用 FFmpeg 实现 RTMP 推流直播
RTMP(Real-Time Messaging Protocol) 是直播行业中常用的传输协议。 一般来说,直播服务商会给你: ✅ 一个 RTMP 推流地址(你推视频上去) ✅ 一个 HLS 或 FLV 拉流地址(观众观看用)…...
