【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 main

import "fmt"

func main() {

    //byte与uint32
    var a byte = 'a'
    var b uint8 = 'a'
    fmt.Println("使用byte类型表示字符:", string(a))    //a
    fmt.Println("使用uint8类型表示字符串: ", string(b)) //a

    fmt.Println("---------------")
    var c rune = 'b'
    var d int32 = 'b'
    fmt.Println("使用rune类型表示字符:", string(c))    //b
    fmt.Println("使用int32类型表示字符串: ", string(d)) //b
}

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


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

demo

package main

import "fmt"

func main() {
    str := "nana"
    s := []byte(str)
    fmt.Println("使用byte类型表示字符串: ", string(s)) //nana

    str1 := "nana"
    s1 := []uint8(str1)
    fmt.Println("使用uint8类型表示字符串: ", string(s1)) //nana

    fmt.Println("____________________")
    str2 := "nanago"
    s2 := []rune(str2)
    fmt.Println("使用rune类型表示字符串: ", string(s2)) //nanago

    str3 := "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 main

import "fmt"

func main() {

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

}

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

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

统计字符串的长度

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

demo


package main

import "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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第十四课:eNSP AAA配置教程

一、AAA介绍 AAA是Authentication(认证)、Authorization(授权)和Accounting(计费)的简称,是一种管理框架,它提供了授权部分用户访问指定资源和记录这些用户操作行为的安全机制。因其…

ip_vs 的管理以及 keepalived + lvs 案例

ip_vs 的管理 ipvsadm 与 keepalived for lvs ipvsadm 命令及参数介绍 部署和配置LVS服务会经常用到一些命令,如ipvsadm,可以使用“ipvsadm -help”命令查看使用帮助。 ipvsadm 命令的常用参数及其说明如下: # 添加虚拟服务器# 语法&#x…

计算机网络自顶向下Wireshark labs1-Intro

Wireshark labs1 实验文档:http://www-net.cs.umass.edu/wireshark-labs/Wireshark_Intro_v8.0.pdf 介绍 加深对网络协议的理解通常可以通过观察协议的运行和不断调试协议来大大加深,具体而言,就是观察两个协议实体之间交换的报文序列&…

python系列-顺序/条件/循环语句

🌈个人主页: 会编程的果子君 ​💫个人格言:“成为自己未来的主人~” 目录 顺序语句 条件语句 什么是条件语句 语法格式 缩进和代码块 空语句pass 循环语句 while循环 for循环 continue break 顺序语句 默认情况下,Python的代码执行…

精准核酸检测 - 华为OD统一考试

OD统一考试(C卷) 分值: 100分 题解: Java / Python / C 题目描述 为了达到新冠疫情精准防控的需要,为了避免全员核酸检测带来的浪费,需要精准圈定可能被感染的人群。 现在根据传染病流调以及大数据分析&a…

Linux第34步_TF-A移植的第2步_修改设备树和tf-a.tsv

在虚拟机中,使用VSCode打开linux /atk-mp1/atk-mp1/my-tfa/目录下tf-a.code-workspace”; 找到“tf-a-stm32mp-2.2.r1/fdts”目录,就是设备树文件所在的目录。 见下图: 一、修改“stm32mp157d-atk.dts” 修改后,见下…

日志平台搭建手册

1. Java环境安装和配置 JDK要求安装1.8版本,安装可以参考《Linux安装JDK完整步骤》。 2. 创建用户 创建elk用户,用来管理elk相关的服务,包括:filebeat、logstash、elasticsearch、kibana。执行命令: useradd elk …

VC++中使用OpenCV进行人脸检测

VC中使用OpenCV进行人脸检测 对于上面的图像,如何使用OpenCV进行人脸检测呢? 使用OpenCV进行人脸检测十分简单,OpenCV官网给了一个Python人脸检测的示例程序, objectDetection.py代码如下: from __future__ import p…

计算机网络-分层结构,协议,接口,服务

文章目录 总览为什么要分层怎样分层正式认识分层概念小结 总览 为什么要分层 发送文件前要做的准备工作很多 把这个准备工作分层小问题解决,也就分层解决 怎样分层 每层相互独立,每层做的工作不同 界面自然清晰,层与层之间的接口能够体现…

(2)(2.1) Andruav Android Cellular(二)

文章目录 前言 5 Andruav Web Client 6 Andruav Telemetry 7 Andruav高级功能 8 将Andruav与SITL配合使用 9 FAQ 10 术语表 前言 Andruav 是一个基于安卓的互联系统,它将安卓手机作为公司计算机,为你的无人机和遥控车增添先进功能。 5 Andruav W…

【Java】IDEA集成开发环境工具切换JDK和设置环境变量

欢迎来到《小5讲堂》 大家好,我是全栈小5。 这是《Java》序列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握…

CTF CRYPTO 密码学-5

题目名称:山岚 题目描述: 山岚 f5-lf5aa9gc9{-8648cbfb4f979c-c2a851d6e5-c} 解题过程: Step1:根据题目提示栅栏加密 分析 观察给出的密文发现有f、l、a、g等字符有规律的夹杂的密文中间,看出都是每3个字符的第1…

只会 Python 不行,不会 Python 万万不行 。。。

当下的环境大家有目共睹,未来一段时间情况如何,想必不少人心里也清楚,技术人走到中年,难免会焦虑,职场上干得不爽,但是跳槽也不容易,加上不少企业裁员,换个满意的工作更是难上加难。…

大学生图像采集上传成功的秘诀被破解了‼️

✅大学生毕业图像采集上传成功了我喜欢的 大学生图像采集可以自己上传 尤其是毕业采集, 很多同学都需要自己拍照上传,只要你照片人像比例对, 像素和大小对,真的分分钟上传成功! 毕业采集照片要求: 像素480*…

Kotlin 尾递归函数

函数式编程中,重要的概念 尾递归: 当一个函数 在最后调用 自身,称为 尾递归,是一种特殊的递归函数。 Kotlin 使用 tailrec 声明尾递归函数,可以避免 StackOverflowError 的风险。 原理是:通过编译器优化 …

泛微E-Cology getLabelByModule SQL注入漏洞复现

0x01 产品简介 泛微协同管理应用平台e-cology是一套兼具企业信息门户、知识文档管理、工作流程管理、人力资源管理、客户关系管理、项目管理、财务管理、资产管理、供应链管理、数据中心功能的企业大型协同管理平台。 0x02 漏洞概述 由于泛微e-cology未对用户的输入进行有效…

一周时间,开发了一款封面图生成工具

介绍 这是一款封面图的制作工具,根据简单的配置即可生成一张好看的封面图,目前已有七款主题可以选择。做这个工具的初衷来自平时写文章,都为封面图发愁,去图片 网站上搜索很难找到满意的,而且当你要的图如果要搭配上文…

【Java】Maven的基本使用

Maven的基本使用 Maven常用命令 complie:编译clean:清理test:测试package:打包install:安装 mvn complie mvn clean mvn test mvn package mvn installMaven生命周期 IDEA配置Maven Maven坐标 什么是坐标?…

【MIMO 从入门到精通】[P8][A Detailed Introduction to Beamforming]

前言: 本篇参考油管 5G Learning 《A Detailed Introduction to Beamforming》 简单介绍一下波束赋形的原理。 电磁波传播的数学模型如下图: 跟水波几乎是一样的,以圆形的均匀波进行传播 在各个方向上面功率大致相同。 但是我们需要方向性更好的电磁…

【赠书第17期】Excel高效办公:文秘与行政办公(AI版)

文章目录 前言 1 了解Excel的强大功能和工具 2 提升Excel技能的方法 3 结合AI技术提升Excel应用 4 注意事项 5 推荐图书 6 粉丝福利 前言 随着人工智能(AI)技术的快速发展,我们的工作方式也在发生深刻变革。其中,Excel 作…