【golang】怎样判断一个变量的类型?

怎样判断一个变量的类型?

package mainimport "fmt"var container = []string{"zero", "one", "two"}
func main() {container := map[int]string{0: "zero", 1: "one", 2: "two"}fmt.Printf("The element is %q.\n", container[1])
}

那么,怎样在打印其中元素之前,正确判断变量container的类型?

典型回答

使用类型断言

value, ok := interface{}(container).([]string)

这里有一条赋值语句。在赋值符号的右边,是一个类型断言表达式。

它包括了用来把container变量的值转换为空接口值的interface{}(container)

以及一个用于判断前者的类型是否为切片类型[]string.([]string)

这个表达式的结果可以被赋给两个变量,在这里由value和ok代表。变量ok是布尔(bool)类型的,它将代表类型判断的结果,true和false。

如果是true,那么被判断的值将会被自动转换为[]string类型的值,并赋给变量value,否则value将被赋予nil(即“空”)。

顺便提一下,这里的ok也可以没有。也就是说,类型断言表达式的结果,可以只被赋给一个变量,在这里是value。

问题解析

类型断言表达式的语法形式是x.(T)。其中的x代表要被判断类型的值。这个值当下的类型必须是接口类型的,不过具体是哪个接口类型其实是无所谓的。

所以,当这里container变量类型不是任何的接口类型时,我们就需要先把它转成某个接口类型的值。

在Go语言中,interface{}代表空接口,任何类型都是它的实现类型。

你可能会对这里的{}产生疑惑,为什么在关键字interface的右边还要加上这个东西?

请记住,一对不包裹任何东西的花括号,除了可以代表空的代码块之外,还可以用于表示不包含任何内容的数据结构(或者说数据类型)。

image.png

我们向答案的最右边看。圆括号中[]string是一个类型字面量。所谓类型字面量,就是用来表示数据类型本身的若干个字符。

比如,string是表示字符串类型的字面量,uint8是表示 8 位无符号整数类型的字面量。再复杂一些的就是我们刚才提到的[]string,用来表示元素类型为string的切片类型,以及map[int]string,用来表示键类型为int、值类型为string的字典类型。

类型转换规则中有哪些值得注意的地方?

类型转换表达式已经在前面展示过,它的语法形式是T(x)。

其中的x可以是一个变量,也可以是一个代表值的字面量(比如1.23和struct{}),还可以是一个表达式。

注意:如果是表达式,那么该表达式的结果只能是一个值,而不能是多个值。在这个上下文中,x可以被叫做源值,它的类型就是源类型,而那个T代表的类型就是目标类型。

类型转化有三个很常用并且非常值得注意的知识点:

一、对于整数类型值、整数常量之间的类型转换,原则上只要源值在目标类型的可表示范围内就是合法的。

比如,之所以uint8(255)可以把无类型的常量255转换成uint8类型的值,是因为255在[0,255]的范围内。

但需要特别注意的是,源整数类型的可表示范围较大,而目标类型的可表示范围较小的情况,比如把值的类型从int16转换为int8。请看下面这段代码:

var srcInt = int16(-255)
dstInt := int8(srcInt)

变量srcInt的值是int16类型的-255,而变量dstInt的值是由前者转换而来的,类型是int8。int16类型的可表示范围可比int8类型大了不少。问题是,dstInt的值是多少?

首先你要知道,整数在 Go 语言以及计算机中都是以补码的形式存储的。这主要是为了简化计算机对整数的运算过程。补码其实就是原码各位求反再加 1。

比如,int16类型的值-255的补码是1111111100000001。如果我们把该值转换为int8类型的值,那么 Go 语言会把在较高位置(或者说最左边位置)上的 8 位二进制数直接截掉,从而得到00000001

又由于其最左边一位是0,表示它是个正整数,以及正整数的补码就等于其原码,所以dstInt的值就是1。
一定要记住,当整数值的类型的有效范围由宽变窄时,只需在补码形式下截掉一定数量的高位二进制数即可

类似的快刀斩乱麻规则还有:当把一个浮点数类型的值转换为整数类型值时,前者的小数部分会被全部截掉。

二、虽然直接把一个整数值转换为一个string类型的值是可行的,但值得关注的是,被转换的整数值应该可以代表一个有效的Unicode代码点,否则转换的结果将会是"�"(仅由高亮的问号组成的字符串值)。

字符"�"的Unicode代码点是U+FFFD。它是Unicode标准中定义的Replacement Character,专用于替换那些未知的、不被认可的以及无法展示的字符。

面试肯定不会去问"哪个整数值转换后会得到哪个字符串",但是可能会写下:

string(-1)

并询问会得到什么?这可是完全不同的问题啊。由于-1肯定无法代表一个有效的Unicode代码点,所以得到的总会是"�"。在实际工作中,我们在排查问题时可能会遇到"�",我们要知道这可能是由于什么引起的。

三、关于string类型与各种切片类型之间的互转的。

一个值在从string类型向[]byte类型转换时代表着以 UTF-8 编码的字符串会被拆分成零散、独立的字节。

除了与ASCII编码兼容的那部分字符集,以 UTF-8 编码的某个单一字节是无法代表一个字符的。

string([]byte{'\xe4', '\xbd', '\xa0', '\xe5', '\xa5', '\xbd'}) // 你好

比如,UTF-8 编码的三个字节\xe4、\xbd和\xa0合在一起才能代表字符’你’,而\xe5、\xa5和\xbd合在一起才能代表字符’好’。

其次,一个值在从string类型向[]rune类型转换时代表着字符串会被拆分成一个个Unicode 字符。

什么是别名类型?什么是潜在类型?

我们可以用关键字type声明自定义的各种类型。当然了,这些类型必须在 Go 语言基本类型和高级类型的范畴之内。在它们当中,有一种被叫做“别名类型”的类型。我们可以像下面这样声明它:

type MyString = string

这条声明语句表示,MyString是string类型的别名类型。顾名思义,别名类型与其源类型的区别恐怕只是在名称上,它们是完全相同的。

源类型与别名类型是一对概念,是两个对立的称呼。别名类型主要是为了代码重构而存在的。

Go 语言内建的基本类型中就存在两个别名类型。byte是uint8的别名类型,而rune是int32的别名类型。

注意,如果我这样声明:

type Mystring2 string //注意,这里没有等号。

MyString2和string就是两个不同的类型了。这里的MyString2是一个新的类型,不同于其他任何类型。

这种方式也可以被叫做对类型的再定义。我们刚刚把string类型再定义成了另外一个类型MyString2。

image.png

对于这里的类型再定义来说,string可以被称为MyString2的潜在类型。潜在类型的含义是,某个类型在本质上是哪个类型。

潜在类型相同的不同类型的值之间是可以进行类型转换的。因此,MyString2类型的值与string类型的值可以使用类型转换表达式进行互转。

但对于集合类的类型[]MyString2与[]string来说这样做却是不合法的,因为[]MyString2与[]string的潜在类型不同,分别是[]MyString2和[]string。另外,即使两个不同类型的潜在类型相同,它们的值之间也不能进行判等或比较,它们的变量之间也不能赋值。

文章来自郝林老师的《Go语言36讲》

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

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

相关文章

享元模式(C++)

定义 运用共享技术有效地支持大量细粒度的对象。 使用场景 在软件系统采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价——主要指内存需求方面的代价。如何在避免大量细粒度对象问题的同时,让外部客户程序仍…

128.【Maven】

Maven仓库 (一)、Maven 简介1.传统项目管理的缺点2.Maven是什么3.Maven的作用 (二)、Maven 的下载与安装1.下载与认识目录2.配置Maven的全局环境 (三)、Maven 的基础概念1.Maven 仓库(1).仓库分类 2. Maven 坐标3.Maven 本地仓库配置(1).改变默认的仓库地址(2).改变远程仓库地址…

mac电脑 node 基本操作命令

1. 查看node的版本 node -v2. 查看可安装的node版本 sudo npm view node versions3. 安装指定版本的node sudo n 18.9.04. 安装最新版本node sudo n latest5. 安装最新稳定版 sudo n stable6. 清楚node缓存 sudo npm cache clean -f7. 列举已经安装的node版本 n ls 8. 在…

【并发编程】无锁环形队列Disruptor并发框架使用

Disruptor 是苹国外厂本易公司LMAX开发的一个高件能列,研发的初夷是解决内存队列的延识问顾在性能测试中发现竟然与10操作处于同样的数量级),基于Disruptor开发的系统单线程能支撑每秒600万订单,2010年在QCn演讲后,获得了业界关注…

c++11-14-17_内存管理(RAII)_多线程

文章目录 前言:什么是RAII?指针/智能指针:使用智能指针管理内存资源:unique_ptr的使用:自定义删除器: shared_ptr的使用:shared_ptr指向同一个对象的不同成员:自定义删除函数&#x…

期权定价模型系列【2】—期权的希腊字母计算及应用

本篇文章旨在介绍期权常见希腊字母的计算及应用 本专栏更多侧重于理论及文字方面的展示,文章具体的代码可以参考我的另一个专栏【期权量化】。 【期权量化】专栏有同名文章,并且给出了文章的具体代码。 专栏地址: http://t.csdn.cn/Y30Hk…

谈谈Java开发语言

目录 1.概念 2.特点 3.应用领域 4.就业情况 1.概念 Java是一种面向对象的编程语言,它由James Gosling和他的团队在1995年于Sun Microsystems(现在是Oracle Corporation)开发出来。Java的设计目标是让开发者能够编写一次代码,在…

Arcgis中POI找到建筑面内距离最近的标准地址通过模型构建器来实现

背景 之前写过一篇文章 Arcgis通过矢量建筑面找到POI对应的标准地址 这里面的大致思路跟本篇文章是类似的,不过上一篇文章有部分有瑕疵,就是在POI去找建筑面内的标准地址时,找到的虽然是建筑面内的,但是不一定是距离最近的&#…

登录界面中图片验证码的生成和校验

一、用pillpw生成图片验证码 1、安装pillow pip install pip install pillow2、下载字体 比如:Monaco.ttf 3、实现生成验证码的方法 该方法返回一个img ,可以把这个img图片保存到内存中,也可以以文件形式保存到磁盘,还返回了验证码的文字…

走出象牙塔:李郓梁的区块链实践之路丨对话MVP

如何从科研走向实践?李郓梁在社区找到了答案。 作为西安工业大学的硕士研究生,李郓梁从学校的实验室接触区块链技术。通过研读大量论文,李郓梁为区块链多中心化、不可篡改等前沿理论深深着迷,并选择将区块链作为主要研究方向&…

使用gewe框架进行微信群组管理(一)

友情链接:geweapi.com 点击访问即可。 管理员操作 小提示: 添加、删除、转让多个wxid时仅限于添加/删除管理员,1添加 2删除 3转让 请求URL: http://域名地址/api/group/admin 请求方式: POST 请求头&#xff1a…

C++实现一键关闭桌面

方法一&#xff1a; C关闭桌面,explorer.exe #include<Windows.h> #include <TlHelp32.h> #include"resource.h" #pragma warning(disable:4996) void taskkill(const char * name) {HANDLE info_handle CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,…

Jmeter —— jmeter设置HTTP信息头管理器模拟请求头

HTTP信息头管理器 HTTP信息头管理器是在有需要模拟请求头部的时候进行设置的&#xff0c;添加方式 是 右击线程组 -- 配置元件 -- HTTP信息头管理器 可以通过抓包工具或者F12获取http请求的header头部信息&#xff1b;如下图&#xff1a; 复制并点击jmeter中的从剪贴板添加&am…

element-plus里,设置Message消息提示框组件显示的位置,垂直居中

element-plus里的 Message 组件&#xff0c;默认展示的位置在最顶部&#xff0c;依次往下叠加&#xff0c;如图所示 想要解决它显示的位置&#xff0c;可以使用组件里的 offset属性&#xff0c;设置 Message 距离窗口顶部的偏移量,想要垂直居中&#xff0c;可以这么设置&#…

2.若依前后端分离版第一个增删查改

1.介绍 若依提供了代码生成功能&#xff0c;单表的CRUD可以直接用若依框架提供的代码生成进行创建。 2.实现 2.1 在数据库创建业务表test_teacher 2.2 生成代码 运行系统&#xff0c;进入菜单[系统工具]-》[代码生成],点击导入按钮&#xff0c;选择需要生成代码的表进行导…

Unity-Shader-高亮Highlight

常用Shader-高亮&#xff0c;可动态调整高亮颜色、高亮强度范围/等级、高亮闪烁速度、高亮状态 Shader "CustomShader/Highlight" {Properties{_Color("Color", Color) (0.9044118,0.6640914,0.03325041,0)_Albedo("Albedo", 2D) "white…

通过OpenTelemetry上报Python-flask应用数据(阿里云)

参考文档 https://help.aliyun.com/document_detail/611711.html?spma2c4g.90499.0.0.34a056ddTu2WWq 先按照 方法一&#xff1a;手动埋点上报Python应用数据 步骤测试上报是否正常。 flas 上报 在 手动埋点上报Python应用数据 的基础上&#xff0c;上报flask应用的数据&#…

Qt 8. UDP客户端通信

1. 代码 //UdpClient.h #ifndef UDPCLIENT_H #define UDPCLIENT_H#include <QtNetwork>class Ex2; // 声明类 class UdpClient : public QObject {Q_OBJECT public:explicit UdpClient(Ex2 *ui nullptr);~UdpClient();void Send(QByteArray buf,QHostAddress addr…

【工作中问题解决实践 九】Spring中事务传播的问题排查

最近在工作中遇到了三个关于事务操作的问题&#xff0c;顺便就着这三个问题又回顾了一遍Spring的事务相关的操作&#xff0c;想着一次性把这个问题研究明白了&#xff0c;后续使用事务的时候也能踏实点&#xff0c;让事务发挥真实的作用 什么是事务&#xff1f;什么是事务管理…

《Linux从练气到飞升》No.12 Linux进程概念

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…