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

news2025/2/24 6:07:36

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

package main

import "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.coloradmin.cn/o/863457.html

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

相关文章

为什么边缘计算一定会迎来大爆发?

边缘计算是指在靠近数据源和终端设备的边缘位置进行数据处理、分析和存储的一种计算模式,相对于传统的云计算中心,它将计算资源尽可能地靠近数据源和终端设备。工业物联网是物联网在工业领域的应用,其中边缘计算在工业物联网中扮演着至关重要…

带你了解—通过远程访问局域网服务区并进行数据采集【内网穿透】

文章目录 前言1.使用cpolar进行局域网数据采集的案例2.远程数据隧道功能 前言 cpolar作为一款轻便易用、功能强大的内网穿透软件,在很多应用场景中都能大显身手。其中最常见的,就是网络网站方面的应用。利用cpolar建立的数据隧道,能够轻松实…

网易互娱出海之旅:大数据平台上云架构设计与实践

2020 年初,随着网易互娱的海外业务增长与海外数据合规的需求,我们开始了网易互娱大数据离线计算平台迁移出海的工作。前期,我们采取了云主机裸机加上高性能 EBS 块存储的方案。但是,这个方案存储费用高昂,成本是国内自…

【强化学习】值函数算法DQNs详解【Vanilla DQN Double DQN Dueling DQN】

DQNs【Vanilla DQN & Double DQN & Dueling DQN】 文章目录 DQNs【Vanilla DQN & Double DQN & Dueling DQN】1. DQN及其变种介绍1.1 Vanilla DQN1.2 Double DQN1.3 Dueling DQN 2. Gym环境介绍2.1 Obseravtion Space2.2 Reward Function2.3 Action Space 3. D…

Vue3 :Pinia入门

Vue3 :Pinia入门 Date: May 11, 2023 Sum: Pinia概念、实现counter、getters、异步action、storeToRefs保持响应式解构 什么是Pinia Pinia 是 Vue 的专属状态管理库,可以实现跨组件或页面共享状态,是 vuex 状态管理工具的替代品&#xff0c…

晨控CK-GW06-E01与汇川H5U系列PLC通讯手册

晨控CK-GW06-E01与汇川H5U系列PLC通讯手册 晨控CK-GW06-E01是一款支持标准工业通讯协议 EtherNet IP 的网关控制器,方便用户集成到PLC等控制系统中。本控制器提供了网络 POE 供电和直流电源供电两种方式,确保用户在使用无 POE 供电功能的交换机时可采用外接电源供电…

18 | 淘宝用户行为分析

分析目的 本报告以淘宝app的用户消费行为数据为数据集,通过行业的指标对淘宝用户行为进行分析,从而探索淘宝用户的行为模式,具体指标包括: 日PV和日UV分析,付费率分析,复购行为分析,漏斗流失分析和用户价值RFM分析。为用户运营更好地解析和管理用户(例如对高价值用户的维…

SpringBoot+Vue3打造企业级一体化PaaS系统

目录 一、前言 二、PaaS的概念 三、PaaS中包含什么? 四、使用PaaS的优势 五、SpringBootVue3打造企业级PaaS系统 六、小结 一、前言 云计算的三种模型是PaaS,SaaS(软件即服务)和IaaS(基础架构即服务)。 Iaa…

陪跑多年,Postgres终崛起封王!(译)

Postgres开源数据库刚刚度过了它的25岁生日。遗憾的是,它既没有凭借数百万美元的风险投资脱颖而出,也没有获得技术布道师DevRel团队的支持,只处于起步阶段,但却一直在更新。 几个月之后,Postgres 16正式版可能会闪亮登…

Active Directory安全和风险状况管理

风险评估和管理 风险评估和管理是主动安全性和合规性管理不可或缺的一部分。 发现关键基础设施组件中的风险行为和配置对于阻止网络入侵和预防网络攻击至关重要。帐户泄露和配置错误漏洞是用于破坏网络的常见技术。当评估、监控和降低 Active Directory 基础架构的风险时&…

阿里云SMS开通流程

No1:登录阿里云首页:选择 产品——>企业服务与云通信——>云通信——>短信服务 No2:选择 免费开通 No3:之后根据提示操作即可。 No4:开通之后效果如图: 至此短信服务已经开通。购买短信包之后便可使用

python异步IO完全指南

原地址:https://flyingbyte.cc/post/async_io/ python异步IO完全指南 做为一种并行编程的範式,异步IO在Python中非常受重视,从Python3.4到3.7快速演进。 我们已经有多线程,多进程,并发(concurrency&#x…

cesium学习记录05-加载数据(矢量、影像、地形、3D模型)

1. 矢量数据: 1.1. GeoJSON 定义: 一个基于JSON的地理数据格式,Cesium支持GeoJSON的直接加载。 例子: 加载一个简易故宫建筑的GeoJSON数据。 代码: /*** 添加故宫geojson数据*/AddGuGong() {var viewer this.v…

提取有像素的掩码和原图

有些数据集给的掩码是全黑图片,需要将全黑的掩码剔除,保留有标签的掩码。 DDR-dataset 眼底图像处理 from PIL import Image import cv2 import osdef extract_mask_and_original(mask_path, original_path, output_folder):# 读取黑白掩码图片和同名原…

UDP 的报文结构和注意事项

目录 一. UDP的特点 二. UDP协议 1. UDP协议端格式 2.UDP的报文结构 3. 基于UDP的应用层协议 三. (高频面试题) 一. UDP的特点 无连接:知道对端的IP和端口号就直接进行传输,不需要建立连接。不可靠:即使因为网络故障等原因无法将数据报发送…

重磅!软考或全部改为机考?

最近,有同学分享了一张署名为“工业和信息化部教育与考试中心”的文件截图。 注:该截图来源于网络,而非官方 以下为该截图文件全文: 关于2023年下半年计算机软件资格考试有关工作调整的通知 各省、自治区、直辖市及计划单列市…

医疗PACS源码,支持三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜

C/S架构的PACS系统源码,PACS主要进行病人信息和影像的获取、处理、存储、调阅、检索、管理,并通过网络向全院提供病人检查影像及诊断报告;各影像科室之间共享不同设备的病人检查影像及诊断报告;在诊断工作站上,调阅HIS中病人的其它…

ThreadLocal的内存泄漏是怎么发生的

前言 在分析ThreadLocal导致的内存泄露前,需要普及了解一下内存泄露、强引用与弱引用以及GC回收机制,这样才能更好的分析为什么ThreadLocal会导致内存泄露呢?更重要的是知道该如何避免这样情况发生,增强系统的健壮性。 内存泄露 …

元宇宙核能发电VR模拟仿真实训教学为建设新型电力系统提供重要支撑

随着“碳达峰、碳中和”目标与建设新型能源体系的提出,在元宇宙环境下建设电力系统是未来发展的趋势。以物联网、区块链、数字孪生、混合现实等技术为主要代表的元宇宙技术体系及其在电力和能源系统中的应用,将会促进智能电网的发展,为建设新…

Win10启动Jmeter报错提示jmeter.log拒绝访问问题

jmeter版本:5.4.1 查看版本 在dos命令窗口中进入jmeter安装目录下的bin目录中:执行jmeter - v命令 我启动的方式是:进入jmeter安装目录下的bin目录中双击jmeter.bat启动的。结果报错,但是不影响使用。 报错日志如下: …