Go语言断言和类型查询

Go语言断言和类型查询

1、类型断言

类型断言(Type Assertion)是一个使用在接口值上的操作,用于检查接口类型变量所持有的值是否实现了期望的接

口或者具体的类型。

在Go语言中类型断言的语法格式如下:

// i.(TypeNname)
value, ok := x.(T)

其中,x 表示一个接口的类型,如果是具体类型变量,则编译器会报non-interface type xxx on left,T 表

示一个具体的类型(也可为接口类型)。

该断言表达式会返回 x 的值(也就是 value)和一个布尔值(也就是 ok),可根据该布尔值判断 x 是否为 T 类

型:

  • 如果 T 是具体某个类型,类型断言会检查 x 的动态类型是否等于具体类型 T。如果检查成功,类型断言返回的

    结果是 x 的动态值,其类型是 T。

  • 如果 T 是接口类型,类型断言会检查 x 的动态类型是否满足 T。如果检查成功,x 的动态值不会被提取,返回

    值是一个类型为 T 的接口值。

  • 无论 T 是什么类型,如果 x 是 nil 接口值,类型断言都会失败。

示例代码如下:

package mainimport ("fmt"
)func main() {var x interface{}x = 10value, ok := x.(int)// 10,truefmt.Print(value, ",", ok)
}

运行结果如下:

# 程序结果
10,true

需要注意如果不接收第二个参数也就是上面代码中的 ok,断言失败时会直接造成一个 panic,如果 x 为 nil 同样也

会 panic。

示例代码如下:

package mainimport ("fmt"
)func main() {var x interface{}x = "Hello"value := x.(int)fmt.Println(value)
}

运行结果如下:

# 输出结果
panic: interface conversion: interface {} is string, not int

接口断言通常可以使用 comma,ok 语句来确定接口是否绑定某个实例类型,或者判断接口绑定的实例类型是否实

现另一个接口。

re,ok := body.(io.ReadCloser)
if,ok :=  r.Body.(*maxBytesReader);

2、类型查询

接口类型查询的语法格式如下:

switch v := i.(type){case typel:XXXXcase type2:XXXXdefault:XXXX
}

接口查询有两层语义,一是查询一个接口变量底层绑定的底层变量的具体类型是什么,二是查询接口变量绑定的底

层变量是否还实现了其他接口。

(1)、i 必须是接口类型

具体类型实例的类型是静态的,在类型声明后就不再变化,所以具体类型的变量不存在类型查询,类型查询一定是

对一个接口变量进行操作。也就是说,上文中的i必须是接口变量,如果i是未初始化接口变量,则v的值是 nil。

package mainimport ("fmt""io"
)func main() {var i io.Reader//此处i是为未初始化的接口变量,所以v为nilswitch v := i.(type) {case nil://<nil>fmt.Printf("%T\n", v)default:fmt.Printf("default")}
}

(2)、case 字句后面可以跟非接口类型名,也可以跟接口类型名,匹配是按照 case 子句的顺序进行的。

  • 如果 case 后面是一个接口类型名,且接口变量i绑定的实例类型实现了该接口类型的方法,则匹配成,v的类

    型是接口类型,v底层绑定的实例是i绑定具体类型实例的副本。

  • 如果 case 后面是一个具体类型名,且接口变量i绑定的实例类型和该具体类型相同,则匹配成功,此时v 就是

    该具体类型变量,v的值是i绑定的实例值的副本。

  • 如果 case 后面跟着多个类型,使用逗号分隔,接口变量i绑定的实例类型只要和其中一个类型匹配,则直接使

    用o赋值给v,相当于 v:=o。这个语法有点奇怪,按理说编译器不应该允许这种操作,语言实现者可能想让

    type switch 语句和普通的 switch 语句保持一样的语法规则,允许发生这种情况。

  • 如果所有的case字句都不满足,则执行 default 语句,此时执行的仍然是 v:=o,最终v的值是o。此时使用v没

    有任何意义。

  • fallthrough 语句不能在 Type Switch 语句中使用。

package mainimport ("fmt""io""log""os"
)func main() {var i io.Reader// 此处i是为未初始化的接口变量,所以v为nilswitch v := i.(type) {case nil:// <nil>fmt.Printf("%T\n", v)default:fmt.Printf("default")}f, err := os.OpenFile("notes.txt", os.O_RDWR|os.O_CREATE, 0755)if err != nil {log.Fatal(err)}defer f.Close()i = fswitch v := i.(type) {// i的绑定的实例是*osFile类型,实现了io.ReadWriter接口,所以下面case匹配成功case io.ReadWriter:// v是io.ReadWriter接口类型,所以可以调用Write方法v.Write([]byte("io.ReadWriter\n"))// Type Switch Result: io.ReadWriterfmt.Println("Type Switch Result: io.ReadWriter")// 由于上一个case已经匹配,就算这个case也匹配,也不会走到这里case *os.File:v.Write([]byte("*os.File\n"))fmt.Println("Type Switch Result: *os.File")//这里可以调用具体类型方法v.Sync()default:fmt.Println("Type Switch Result: unknown")return}switch v := i.(type) {// 匹配成功,v的类型就是具体类型*os.Filecase *os.File:v.Write([]byte("*os.File\n"))// Type Switch Result: *os.Filefmt.Println("Type Switch Result: *os.File")v.Sync()//由于上一个case已经匹配,就算这个case也匹配,也不会走到这里case io.ReadWriter://v是io.ReadWriter接口类型,所以可以调用Write方法v.Write([]byte("io.ReadWriter\n"))fmt.Println("Type Switch Result: io.ReadWriter")default:fmt.Println("Type Switch Result: unknown")return}switch v := i.(type) {//多个类型,f满足其中任何一个就算匹配case *os.File, io.ReadWriter:// 此时相当于执行力v := i ,v和i是等价的,使用v没有意义。if v == i {// truefmt.Println(true)}default:return}
}
# 程序输出
<nil>
Type Switch Result: io.ReadWriter
Type Switch Result: *os.File
true
package mainimport ("fmt"
)func main() {var a inta = 10// the type of a is intgetType(a)
}func getType(a interface{}) {switch a.(type) {case int:fmt.Println("the type of a is int")case string:fmt.Println("the type of a is string")case float64:fmt.Println("the type of a is float")default:fmt.Println("unknown type")}
}
# 程序输出
the type of a is int

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

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

相关文章

面试算法92:翻转字符

题目 输入一个只包含’0’和’1’的字符串&#xff0c;其中&#xff0c;‘0’可以翻转成’1’&#xff0c;‘1’可以翻转成’0’。请问至少需要翻转几个字符&#xff0c;才可以使翻转之后的字符串中所有的’0’位于’1’的前面&#xff1f;翻转之后的字符串可能只包含字符’0’…

web服务器nginx和Apache有什么区别?

随着互联网的快速发展&#xff0c;Web服务器在互联网应用中扮演着越来越重要的角色。其中&#xff0c;Nginx和Apache是两种广泛使用的Web服务器软件。尽管它们都可以实现Web服务器的功能&#xff0c;但Nginx和Apache在许多方面存在一些重要的区别。本文将探讨Nginx和Apache之间…

Iceberg: 列式读取Parquet数据

两种BaseBatchReader的实现类 BaseBatchReader支持以Batch Vectorized的特性&#xff0c;读取底层的文件。 ColumnarBatchReader 通过VectorizedSparkParquetReaders::build Reader()静态方法创建的读取器&#xff0c;关键特性如下&#xff1a; 支持读取Delete File以Arrow的格…

大数据技术在民生资金专项审计中的应用

一、应用背景 目前&#xff0c;针对审计行业&#xff0c;关于大数据技术的相关研究与应用一般包括大数据智能采集数据技术、大数据智能分析技术、大数据可视化分析技术以及大数据多数据源综合分析技术。其中&#xff0c;大数据智能采集数据技术是通过网络爬虫或者WebService接…

Docker无法启动Postgresql容器

目录 问题描述解决问题 问题描述 拉取了一个Postgresql14.2的镜像&#xff0c;在docker run创建并运行容器之后使用docker ps发现容器没有跑起来&#xff0c;再次使用docker start也没跑起来。 docker run -d --name mypg -v psql-data:/var/lib/postgresql/data -e POSTGRES…

Python random模块(获取随机数)常用方法和使用例子

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 random.random random.random()用于生成一个0到1的随机符点数: 0 < n < 1.0 random.uniform random.uniform(a, b)&#xff0c;用于生成一个指定范围内的随机符点数&#xff0c;两个参数其中一个是上限&#xff0c;一…

2023-我的CSDN创作之旅

1.博客内容与数量 2023年共发表博客59篇&#xff0c;内容主要集中在GIS&#xff0c;空间分析等领域 主要内容有&#xff1a; networkx学习 Geospatial Data Science Geocomputation ESDA in PySal SHAP Spatial Data Analysis BikeDNA 以下是对这几个章节主要内容的简…

机器学习 -- k近邻算法

场景 我学习Python的初衷是学习人工智能&#xff0c;满足现有的业务场景。所以必须要看看机器学习这一块。今天看了很久&#xff0c;做个总结。 机器学习分为深度学习和传统机器学习 深度学习 深度学习模型通常非常复杂&#xff0c;包含多层神经网络&#xff0c;每一层都包含…

在SQL脚本中删除所有的 prompt那一行

在SQL脚本中删除所有的 prompt 命令&#xff0c;您可以手动编辑SQL文件&#xff0c;移除所有包含 prompt 关键字的行。具体操作取决于您使用的是哪种文本编辑器。大多数文本编辑器支持查找和替换功能&#xff0c;可以用它来删除所有 prompt 行。 以下是在不同编辑器中进行操作…

html+css 对input的使用以及详解

表单 form标签主要用于收集用户信息&#xff0c;对表单结果的处理和发送 使用场景&#xff1a;登录页面、注册页面、搜索区域 form属性描述action规定当提交表单时向何处发送表单数据method规定用于发送表单数据的 HTTP 方法name规定表单的名称target规定在何处打开 action …

mysql知识学习

0 mysql的隔离级别有4个&#xff0c;读未提交&#xff0c; 读已提交&#xff08;rc&#xff09;&#xff0c; 可重复读&#xff08;rr&#xff09;,串行化&#xff0c;mysql默认的隔离级别时rr 1聚簇索引就是主键索引&#xff0c; 可以一步到位i的索引 非聚簇索引就是要通过二…

Golang - http请求InsecureSkipVerify 字段为 true 来忽略忽略 SSL验证

在Golang中&#xff0c;可以通过设置 tls.Config 的 InsecureSkipVerify 字段为 true 来忽略 SSL 验证。 下面是一个简单的示例代码&#xff1a; package mainimport ("crypto/tls""fmt""net/http" )func main() {// 创建一个自定义的 Transp…

矩阵式键盘按键值的数码管显示实验

#include<reg51.h> //包含51单片机寄存器定义的头文件 sbit P14P1^4; //将P14位定义为P1.4引脚 sbit P15P1^5; //将P15位定义为P1.5引脚 sbit P16P1^6; //将P16位定义为P1.6引脚 sbit P17P1^7; //将P17位定义为P1.7引脚 unsigned char code Tab[ ]…

CTF-PWN-栈溢出-高级ROP-【SROP】

文章目录 linux信息处理2017 360春秋杯 smallest检查源码思路第一次要执行ret时的栈执行write函数时修改rsp到泄露的栈地址上去 输入/bin/sh并sigreturn调用系统调用回忆exp注意一个离离原上谱的地方 参考链接 SROP(Sigreturn Oriented Programming) 于 2014 年被 Vrije Univer…

简单多状态dp问题(打家劫舍Ⅱ)

通过分类谈论&#xff0c;将环形的问题&#xff0c;转化成两个线性的 “ 打家劫舍Ⅰ ” 1.状态表示 2.状态转移方程 3.初始化 f[ 0 ] nums[ 0 ] g[ 0 ] 0 4.填表顺序 从左往右填表&#xff0c;两个表一块填 5.返回值 max( f[ n-1 ] , g [ n - 1 ] )

【Bug】Android BottomNavigationView 图标黑色色块问题

最近在研究Android Jetpack组件&#xff0c;在使用Navigation配合底部导航栏时&#xff0c;发现一个奇怪的问题&#xff0c;如下&#xff1a; 说明&#xff1a;图标来源于Iconfont开源图标库 我的第三个图标变成了一个黑色色块&#xff0c;这个问题前两天我遇见过&#xff0c…

.NetCore部署微服务(一)

目录 前言 什么是微服务 微服务的优势 微服务的原则 创建项目 在Docker中运行服务 客户端调用 简单的集群服务 前言 写这篇文章旨在用最简单的代码阐述一下微服务 什么是微服务 微服务描述了从单独可部署的服务构建分布式应用程序的体系结构流程&#xff0c;同时这些…

C# 使用Microsoft消息队列(MSMQ)

写在前面 Microsoft Message Queuing (MSMQ) 是在多个不同的应用之间实现相互通信的一种异步传输模式&#xff0c;相互通信的应用可以分布于同一台机器上&#xff0c;也可以分布于相连的网络空间中的任一位置。 使用消息队列可以实现异步通讯&#xff0c;无需关心接收端是否在…

海康威视摄像头+服务器+录像机配置校园围墙安全侦测区域入侵侦测+越界侦测.docx

一、适用场景 1、校园内&#xff0c;防止课外时间翻越围墙到校外、从校外翻越围墙到校内&#xff1b; 2、通过服务器摄像头的侦测功能及时抓图保存&#xff0c;为不安全因素提供数字化依据&#xff1b; 3、网络录像机保存监控视频&#xff0c;服务器保存抓拍到的入侵与越界&am…

UI自动化Selenium iframe切换多层嵌套

IFRAME是HTML标签&#xff0c;作用是文档中的文档&#xff0c;或者浮动的框架(FRAME)。iframe元素会创建包含另外一个文档的内联框架(即行内框架)。 简单来说&#xff0c;就像房子内的一个个房间一样&#xff1b;你要去房间里拿东西&#xff0c;就得先开门&#xff1b; 如上图…