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

2024-01-21 14:28
文章标签 类型 go 使用 认识 byte rune

本文主要是介绍【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

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

这篇关于【Go】rune和byte类型的认识与使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/629833

相关文章

python之uv使用详解

《python之uv使用详解》文章介绍uv在Ubuntu上用于Python项目管理,涵盖安装、初始化、依赖管理、运行调试及Docker应用,强调CI中使用--locked确保依赖一致性... 目录安装与更新standalonepip 安装创建php以及初始化项目依赖管理uv run直接在命令行运行pytho

C#使用Spire.XLS快速生成多表格Excel文件

《C#使用Spire.XLS快速生成多表格Excel文件》在日常开发中,我们经常需要将业务数据导出为结构清晰的Excel文件,本文将手把手教你使用Spire.XLS这个强大的.NET组件,只需几行C#... 目录一、Spire.XLS核心优势清单1.1 性能碾压:从3秒到0.5秒的质变1.2 批量操作的优雅

Kotlin 枚举类使用举例

《Kotlin枚举类使用举例》枚举类(EnumClasses)是Kotlin中用于定义固定集合值的特殊类,它表示一组命名的常量,每个枚举常量都是该类的单例实例,接下来通过本文给大家介绍Kotl... 目录一、编程枚举类核心概念二、基础语法与特性1. 基本定义2. 带参数的枚举3. 实现接口4. 内置属性三、

Java List 使用举例(从入门到精通)

《JavaList使用举例(从入门到精通)》本文系统讲解JavaList,涵盖基础概念、核心特性、常用实现(如ArrayList、LinkedList)及性能对比,介绍创建、操作、遍历方法,结合实... 目录一、List 基础概念1.1 什么是 List?1.2 List 的核心特性1.3 List 家族成

Go中select多路复用的实现示例

《Go中select多路复用的实现示例》Go的select用于多通道通信,实现多路复用,支持随机选择、超时控制及非阻塞操作,建议合理使用以避免协程泄漏和死循环,感兴趣的可以了解一下... 目录一、什么是select基本语法:二、select 使用示例示例1:监听多个通道输入三、select的特性四、使用se

Go语言使用Gin处理路由参数和查询参数

《Go语言使用Gin处理路由参数和查询参数》在WebAPI开发中,处理路由参数(PathParameter)和查询参数(QueryParameter)是非常常见的需求,下面我们就来看看Go语言... 目录一、路由参数 vs 查询参数二、Gin 获取路由参数和查询参数三、示例代码四、运行与测试1. 测试编程路

Python使用python-pptx自动化操作和生成PPT

《Python使用python-pptx自动化操作和生成PPT》这篇文章主要为大家详细介绍了如何使用python-pptx库实现PPT自动化,并提供实用的代码示例和应用场景,感兴趣的小伙伴可以跟随小编... 目录使用python-pptx操作PPT文档安装python-pptx基础概念创建新的PPT文档查看

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点

MySQL中优化CPU使用的详细指南

《MySQL中优化CPU使用的详细指南》优化MySQL的CPU使用可以显著提高数据库的性能和响应时间,本文为大家整理了一些优化CPU使用的方法,大家可以根据需要进行选择... 目录一、优化查询和索引1.1 优化查询语句1.2 创建和优化索引1.3 避免全表扫描二、调整mysql配置参数2.1 调整线程数2.

C#中SortedSet的具体使用

《C#中SortedSet的具体使用》SortedSet是.NETFramework4.0引入的一个泛型集合类,它实现了一个自动排序的集合,内部使用红黑树数据结构来维护元素的有序性,下面就来介绍一下如... 目录基础概念主要特性创建和初始化基本创建方式自定义比较器基本操作添加和删除元素查询操作范围查询集合运