go - 识别存储在 go 接口中的实际类型
问题描述
在下面的代码中
var r io.Reader
c, _ := net.Dial("tcp", ":8080")
r = c
switch r.(type) {
case io.Reader:
fmt.Println("r implements the reader interface")
// fallthrough
case io.Writer:
fmt.Println("r implements the writer interface")
case net.Conn:
fmt.Println("r implements the conn interface")
}
第一个case
语句是始终执行的语句。
如果我取消注释fallthrough
代码将无法编译,因为fallthrough
类型开关中不允许这样做
如果我没记错,go
接口有 2 个值:
- 存储在接口中的实际类型(描述符)(例如
io.Writer
,io.Reader
等) - 存储在其中的值
既然r
显然满足上述所有case
陈述,那么找到存储在中的确切类型的方法是什么r
?
是不是只能通过反射才能完成这个锥体?
解决方案
类型切换和类型断言可用于检查接口值是否包含具体类型的值(同时提取该具体类型的值)。如果您检查的类型(或断言类型)是接口类型(而不是具体类型),则如果具体类型实现给定的接口类型,则大小写将匹配(或断言将成立)。
net.Conn
是一个接口,它是io.Reader
和的超集io.Writer
。如果某物 implements net.Conn
,它也会自动实现io.Reader
and io.Writer
,所以如果你先检查io.Reader
,那将匹配(如果类型也 implements net.Conn
)。
如果您想使用类型开关检查已实现的接口,请先检查net.Conn
,如果未实现,请列出io.Reader
并io.Writer
稍后。
switch r.(type) {
case net.Conn:
fmt.Println("r implements the conn interface")
case io.Reader:
fmt.Println("r implements the reader interface")
case io.Writer:
fmt.Println("r implements the writer interface")
}
如果我没记错的话,go 接口有 2 个值:
- 存储在接口中的实际类型(描述符)(例如 io.Writer、io.Reader 等)
- 存储在其中的值
你没有错,但你错过了一个关键点:实际的具体类型。io.Conn
并且io.Reader
不是具体类型,它们是接口类型。
可能返回的示例具体net.Dial()
类型是*net.TCPConn
。
推荐阅读
- windows - 将批处理转换为 VBS 脚本
- msbuild - MSBuild GenerateResource 任务生成命名空间不完整的资源文件名,导致我们的应用在运行时崩溃
- powershell - Powershell同步重命名目录中的文件
- tesseract - 使用 tesseract 对简单图像进行 OCR 识别的准确率低得惊人。我该如何改进它?
- python - 如何使用 OpenCV 和 Python 创建语义图
- python - Python /Pandas 使用 ibm_db 将数据帧插入 DB2 表
- c++ - 在 QWidget 内的 QGraphicsScene 内绘制
- replace - 如何使用查找和替换交换 Visual Studio Code 中的两个单词?
- git - 使用 Git 将我的生产文件与我提交的开发文件同步的正确术语是什么?
- typescript - Dialogflow & Express -- 履行