【Go面试向】rune和byte类型的认识与使用

【Go】rune和byte类型的认识与使用

大家好 我是寸铁👊
总结了一篇rune和byte类型的认识与使用的文章✨
喜欢的小伙伴可以点点关注 💝

byte和rune类型定义

byte,占用1个字节,共8个比特位,所以它实际上和uint8没什么本质区别,它表示的是一个ASCII码字符。

rune,占用4个字节,共32个比特位,所以它实际上和int32没什么本质区别,它表示的是一个Unicode字符
(Unicode是一种能表示世界上绝大部分字符的编码格式)


不妨来验证一下,能否用uint8和byte一样去表示一个字符,能否用int32和rune一样去表示一个字符?

Demo

package mainimport "fmt"func main() {//byte与uint32var a byte = 'a'var b uint8 = 'a'fmt.Println("使用byte类型表示字符:", string(a))    //afmt.Println("使用uint8类型表示字符串: ", string(b)) //afmt.Println("---------------")var c rune = 'b'var d int32 = 'b'fmt.Println("使用rune类型表示字符:", string(c))    //bfmt.Println("使用int32类型表示字符串: ", string(d)) //b
}

运行结果如下:
答案是可以的,也证明了这两种实际上并无本质区别。
在这里插入图片描述


这次来验证一下,能否用uint8和byte数组去表示一个字符串,能否用int32和rune数组一样去表示一个字符串?

demo

package mainimport "fmt"func main() {str := "nana"s := []byte(str)fmt.Println("使用byte类型表示字符串: ", string(s)) //nanastr1 := "nana"s1 := []uint8(str1)fmt.Println("使用uint8类型表示字符串: ", string(s1)) //nanafmt.Println("____________________")str2 := "nanago"s2 := []rune(str2)fmt.Println("使用rune类型表示字符串: ", string(s2)) //nanagostr3 := "nanago"s3 := []int32(str3)fmt.Println("使用int32类型表示字符串: ", string(s3)) //nanago
}

运行结果如下:
答案是可以的,也证明了这两种实际上并无本质区别。
在这里插入图片描述


有人会问:既然本质没什么区别,为什么还要创建byte和rune类型?

这就涉及到类型别名的概念,众所周知,Go语言有两种类型声明方式:一种叫类型定义声明;另一种叫类型别名声明。其中,别名的使用在大型项目重构中作用最为明显,它能够解决代码升级或者迁移过程中可能存在的类型兼容性问题。而runebyte是Go语言中仅有的两个类型别名,专门用于处理字符。当然,我们可以通过type等关键字加=号的方式声明更多的类型别名。

rune的使用

我们知道,字符串由字符组成,字符的底层由字节组成,而一个字符串的底层的表示是一个字节序列(数组)。在Go语言中,字符可以被分成两种类型处理: 对占一个字节的英文类字符,可以使用byte或者uint8。对占1~4个字节的其他字符,可以使用rune或者int32,如中文、日文、特殊符号等。
示例说明:

rune类型表示中文符号

如下图:这说明可以用rune表示中文符号,不能用byte表示中文符号,没有定义rune类型去表示中文符号,会出现溢出现象。
为什么会出现精度溢出?
很明显,刚才说到byte是一个字节,而rune1~4个字节。我们知道,英文是1个字节,中文是3个字节。byte最多只能表示一个字节的字符,但是,中文是3个字节的,byte1个字节去表示3个字节的字符,必定是不够的,也就造成overflow(溢出)现象。

demo


package mainimport "fmt"func main() {//使用rune类型表示一个中文 一个字符 字节序列var a rune = '云'fmt.Println(string(a))var b byte = '云'fmt.Println(string(b))//统计带中文的字符串长度}

运行结果如下:
在这里插入图片描述

所以,rune的第一个作用是表示中文符号。

统计字符串的长度

举个例子:统计带中文的字符串的长度

demo


package mainimport "fmt"func main() {//统计带中文字符串的长度fmt.Println(len("Go语言编程")) //14//转换为rune数组后统计带中文字符串的长度fmt.Println(len([]rune("Go语言编程"))) //6}

运行结果如下:
在这里插入图片描述

分析一下结果:为什么直接打印就是14,转换为rune[]数组后打印为6?
分析:字符串在底层表示的是一个字节(byte)序列。其中,英文字符占用1个字节,中文字符占用3个字节。所以得到的是1+1+3*4 = 14,是底层中字节序列占用字节的长度,而不是字符的长度。使用rune[]数组后,便可以统计出带中文字符串的字符长度

所以,第二个功能是统计字符串的长度。

截取字符串

举个例子:截取带中文的字符串
截取Go语言这一段,字符串的底层是一个字节序列(数组),字符串的截取 左闭右开 1+1+3+3=8 下标从0开始,起始索引为0,终止索引为8(考虑到右边为开区间)。

demo

    s := "Go语言编程"fmt.Println(s[0:8])//字符串的截取 左闭右开 1+1+3+3=8 下标从0开始

运行结果如下:
在这里插入图片描述

结果是对的,但是存在一个缺陷:就是每次截取时,必须先计算出需要截取的字符串的字节索引,如果说字节数计算错误,就会出现乱码的情况。

验证一下:

s := "Go语言编程"
fmt.Println(s[0:7])
s2 := "Go语言编程"
fmt.Println(s2[0:4])

运行结果如下:
很明显,出现乱码的情况。
在这里插入图片描述

除此之外,假设字符串的长度非常大,通过字节的方式去截取显然不是一个高效的方法。应该是取出字符的方式去截取字符串,rune类型便可以实现这一点。其实,从刚才的len取出byterune数组的长度就可以知道,rune是直接操作字符,而不是像byte一样去一个个操作字节。

使用rune类型运行截取字符串运行结果如下:
在这里插入图片描述

所以,rune的第三个功能是截取字符串。

rune实现分析

为什么rune类型可以做到这一点?
简述:
首先,先弄清楚string、byte、rune三者之间的关系。
字符串在底层的表示是由单个字节组成的一个不可修改的字节序列,字节使用UTF-8编码标识Unicode文本。Unicode文本意味着.go文件可以包含世界上的任意语言或者字符,该文件在任意系统上打开都不会乱码UTF-8Unicode的一种实现方式,是一种针对Unicode可变长度的字符编码,它定义了字符串以何种方式存储在内存中UTF-8使用1~4为每个字符编码。
Go语言把字符分为byterune两种类型处理,byteuint8类型的别名,用于存放占用1个字节的ASCII字符,如英文字符,返回的是字符的原始字节rune类型是int32类型的别名,用于存放多字节字符,如占3个字节的中文字符,返回的是字符Unicode码点值

验证一下
说明上述的分析成立!
demo

s := "Go语言编程"
fmt.Println("byte类型: ", []byte(s))
//输出: byte类型:  [71 111 232 175 173 232 168 128 231 188 150 231 168 139]fmt.Println("rune类型: ", []rune(s))
//输出: rune类型:  [71 111 35821 35328 32534 31243]

具体实现细节参考下面网址:
https://www.cnblogs.com/cheyunhua/p/16007219.html

看到这里的小伙伴,恭喜你又掌握了一个知识点👊
希望大家能取得胜利,坚持就是胜利💪
我是寸铁!我们下期再见💕

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

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

相关文章

Joern环境的安装(Windows版)

Joern环境的安装(Windows版) 网上很少有关于Windows下安装Joern的教程,而我最初使用也是装在Ubuntu虚拟机中,这样使用很占内存,影响体验感。在Windows下使用源码安装Joern也是非常简单的过程: 提前需要的本地环境: …

基于Java+SSM框架的办公用品管理系统详细设计和实现【附源码】

基于JavaSSM框架的办公用品管理系统详细设计和实现【附源码】 🍅 作者主页 央顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各种定…

GO 中如何防止 goroutine 泄露

文章目录 概述如何监控泄露一个简单的例子泄露情况分类chanel 引起的泄露发送不接收接收不发送nil channel真实的场景 传统同步机制MutexWaitGroup 总结参考资料 今天来简单谈谈,Go 如何防止 goroutine 泄露。 概述 Go 的并发模型与其他语言不同,虽说它…

蓝天采集器,功能逆天的网站数据抓取神器,轻松助你成为采集达人,附带搭建配置文档

源码介绍 蓝天采集器是一款专为web服务器打造的数据采集神器。与市面上常见的桌面端采集工具(如火车头等)相比,蓝天采集器在易用性、上手成本和灵活性方面更胜一筹。它部署简便,无需复杂的设置,即可迅速融入您的web服…

详解IP安全:IPSec协议簇 | AH协议 | ESP协议 | IKE协议_ipsec esp

目录 IP安全概述 IPSec协议簇 IPSec的实现方式 AH(Authentication Header,认证头) ESP(Encapsulating Security Payload,封装安全载荷) IKE(Internet Key Exchange,因特网密钥…

storm统计服务开启zookeeper、kafka 、Storm(sasl认证)

部署storm统计服务开启zookeeper、kafka 、Storm(sasl认证) 当前测试验证结果: 单独配置zookeeper 支持acl 设置用户和密码,在storm不修改代码情况下和kafka支持当kafka 开启ACL时,storm 和ccod模块不清楚配置用户和密…

2018年认证杯SPSSPRO杯数学建模A题(第二阶段)海豚与沙丁鱼全过程文档及程序

2018年认证杯SPSSPRO杯数学建模 基于聚类分析的海豚捕食合作策略 A题 海豚与沙丁鱼 原题再现: 沙丁鱼以聚成大群的方式来对抗海豚的捕食。由于水下光线很暗,所以在距离较远时,海豚只能使用回声定位方法来判断鱼群的整体位置,难…

第4章 C++的类

类的保留字:class、struct 或 union 可用来声明和定义类。类的声明由保留字class、struct或union加上类的名称构成。类的定义包括类的声明部分和类的由{}括起来的主体两部分构成。类的实现通常指类的函数成员的实现,即定义类的函数成员。 class 类名;//…

C#,字符串匹配(模式搜索)Sunday算法的源代码

Sunday算法是Daniel M.Sunday于1990年提出的一种字符串模式匹配算法。 核心思想:在匹配过程中,模式串并不被要求一定要按从左向右进行比较还是从右向左进行比较,它在发现不匹配时,算法能跳过尽可能多的字符以进行下一步的匹配&…

港科夜闻|香港科大团队研发多功能,可重构和抗破坏单线感测器阵列

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大团队研发多功能、可重构和抗破坏单线感测器阵列。研究人员开发出一种受人类听觉系统启发的感测器阵列设计技术。透过模仿人耳根据音位分布来区分声音的能力,这种新型感测器阵列方法可能优化感测器阵列…

Yolov8_使用自定义数据集训练模型1

前面几篇文章介绍了如何搭建Yolov8环境、使用默认的模型训练和推理图片及视频的效果、并使用GPU版本的torch加速推理、导出.engine格式的模型进一步利用GPU加速,本篇介绍如何自定义数据集,这样就可以训练出识别特定物体的模型。 《Yolov8_使用自定义数据…

innoDB存储引擎

1.逻辑存储结构 行数据->行->页->区->段->表空间 表空间(ibd文件),一个mysql实例可以对应多个表空间,来存储记录,索引等数据。 段:分为数据段和索引段,回滚段,数据段就是B树的叶子节点&am…

HR3D+HRAuido+HRUI+HR3D_Plugins(游戏引擎源码)

国内知名游戏公司开发的游戏引擎,简洁高效,代码值得参考。包含了这几部分:HR3DHRAuidoHRUIHR3D_Plugins HR3DHRAuidoHRUIHR3D_Plugins(游戏引擎源码) 下载地址: 链接:https://pan.baidu.com/s/1…

使用xbindkeys设置鼠标侧键

1.安装如下包 sudo apt install xbindkeys xautomation 2.生成配置文件 xbindkeys --defaults > $HOME/.xbindkeysrc 3.确定侧键键号 在终端执行下面的代码: xev | grep button 此时会出现如下窗口,将鼠标指针移动到这个窗口上: 单…

【机器学习】调配师:咖啡的完美预测

有一天,小明带着一脸期待找到了你这位数据分析大师。他掏出手机,屏幕上展示着一份详尽的Excel表格。“看,这是我咖啡店过去一年的数据。”他滑动着屏幕,“每个月的销售量、广告投入,还有当月的气温,我都记录…

【MYSQL】事务隔离级别

脏读、幻读、不可重复读 脏读 一个事务正在对一条记录做修改,在这个事务完成并提交前,另一个事务也来读取同一条记录,读取了这些未提交的“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形…

【控制篇 / 分流】(7.4) ❀ 01. 对指定IP网段访问进行分流 ❀ FortiGate 防火墙

【简介】公司有两条宽带,一条ADSL拨号用来上网,一条移动SDWAN,已经连通总部内网服务器,领导要求,只有访问公司服务器IP时走移动SDWAN,其它访问都走ADSL拨号,如果你是管理员,你知道有…

自定义 React Hooks:编写高效、整洁和可重用代码的秘密武器

欢迎来到神奇的 React 世界 大家好!在 React 的世界中,有一个强大的秘密武器,它往往隐藏在显而易见的地方,由于缺乏理解或熟悉而没有得到充分利用。 这个强大的工具,被称为自定义 React hooks,可以彻底改变我们编写 React 应用程序代码的方式。通过提取组件中的有状态逻辑,自…

查找局域网树莓派raspberry的mac地址和ip

依赖python库: pip install socket pip install scapy运行代码: import socket from scapy.layers.l2 import ARP, Ether, srpdef get_hostname(ip_address):try:return socket.gethostbyaddr(ip_address)[0]except socket.herror:# 未能解析主机名ret…

Electron Apple SignIn 登录

本人写博客,向来主张:代码要完整,代码可运行,文中不留下任何疑惑。 最讨厌写博客,代码只留下片段,文中关键的东西没写清楚。之前看了那么多文章,就是不告诉我clientId从哪来的。 官方资料地址&…