【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/336510.html

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

相关文章

Windows11开启SSH服务

文章目录 环境背景安装SSH服务配置SSH服务启动/停止SSH服务登录接下来参考 环境 Windows 11 家庭中文版 背景 在我的Windows电脑上,有些网站无法直接访问,所以需要通过Mac来代理。为此,需要创建一个位于Windows和Mac之间的SSH tunnel。 在…

【C++】vector容器接口要点的补充

接口缩容 在VS编译器的模式下&#xff0c;类似于erase和insert接口的函数通常会进行缩容&#xff0c;因此&#xff0c;insert和erase行参中的迭代器可能会失效。下图中以erase为例&#xff1a; 代码如下&#xff1a; #include <iostream> #include <vector> #inclu…

如何本地部署虚VideoReTalking

环境&#xff1a; Win10专业版 VideoReTalking 问题描述&#xff1a; 如何本地部署虚VideoReTalking 解决方案&#xff1a; VideoReTalking是一个强大的开源AI对嘴型工具&#xff0c;它是我目前使用过的AI对嘴型工具中效果最好的一个&#xff01;它是由西安电子科技大学、…

MATLAB聚类工具箱

本文借鉴了数学建模清风老师的课件与思路&#xff0c;可以点击查看链接查看清风老师视频讲解&#xff1a;【1】MATLAB聚类工具箱&#xff1a;提前预览工具箱的核心功能_哔哩哔哩_bilibili 关于工具箱的获取&#xff0c;在数学建模学习交流公众号里发送&#xff1a; 567891 %% …

idea 安装免费Ai工具 codeium

目录 概述 ide安装 使用 chat问答 自动写代码 除此外小功能 概述 这已经是我目前用的最好免费的Ai工具了&#xff0c;当然你要是有钱最好还是用点花钱的&#xff0c;比如copilot&#xff0c;他可以在idea全家桶包括vs&#xff0c;还有c/c的vs上运行&#xff0c;还贼强&am…

数据加密-mysql

想要实现数据加密可以在mysql数据库表实现数据加密&#xff0c;来确保数据安全。下面就是加密算法AES_ENCRYPT&#xff0c;其他加密算法类似。 1 创建一张临时表test_table CREATE TABLE test_table (name varchar(20) DEFAULT NULL,id blob ) ENGINEInnoDB DEFAULT CHARSETu…

【JavaEE】_基于UDP实现网络通信

目录 1. 服务器 1.1 实现逻辑 1.2 代码 1.3 部分代码解释 2. 客户端 2.1 实现逻辑 2.2 代码 2.3 客户端部分代码解释 3. 程序运行结果 4. 服务器客户端交互逻辑 此篇内容为实现UDP版本的回显服务器echo server&#xff1b; 普通服务器&#xff1a;收到请求&#xff…

领略指针之妙

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

【高等数学之极限】

一、引言 我们先思考一下&#xff0c;上面三个表达式&#xff0c;是否可以将极限值直接代入求值&#xff0c;我们在计算之前需要先分析一下&#xff0c;如果将极限值代入&#xff0c;那么表达式将会变成什么形式? 经过上面的分析&#xff0c;我们发现第一个式子可以直接带入&a…

微电网优化MATLAB:遗传算法(Genetic Algorithm,GA)求解微电网优化(提供MATLAB代码)

一、微网系统运行优化模型 微电网优化是指通过对微电网系统中各个组件的运行状态进行监测和调节&#xff0c;以实现微电网系统的高效运行和能源利用的最大化。微电网是由多种能源资源&#xff08;如太阳能、风能、储能等&#xff09;和负载&#xff08;如建筑、工业设备等&…

通用人工智能的能力评估框架-Levels of AGI Operationalizing Progress on the Path to AGI

通用人工智能的能力评估框架-Levels of AGI: Operationalizing Progress on the Path to AGI 译自’Levels of AGI: Operationalizing Progress on the Path to AGI’&#xff0c;有所删节.笔者能力有限&#xff0c;敬请勘误。 摘要 Google DeepMind提出一种针对通用人工智能 …

端口映射的定义、特点、场景、实例、常见问题回答(Port Mapping)

目 录 一、端口映射&#xff08;Port Mapping&#xff09; 二、端口映射应用场景&#xff08;什么时候用到端口映射&#xff09; &#xff08;一&#xff09;、使用端口映射的条件 &#xff08;二&#xff09;使用端口映射的具体场景 三、端口映射技术的特点 …

LLM之RAG实战(十七)| 高级RAG:通过使用LlamaIndex重新排序来提高检索效率

基本RAG的检索是静态的&#xff0c;会检索到固定数字&#xff08;k&#xff09;个相关文档&#xff0c;而如果查询需要更多的上下文&#xff08;例如摘要&#xff09;或更少的上下文&#xff0c;该怎么办&#xff1f; 可以通过在以下两个阶段来实现动态检索&#xff1a; 预检索…

Python对Excel文件中不在指定区间内的数据加以去除的方法

本文介绍基于Python语言&#xff0c;读取Excel表格文件&#xff0c;基于我们给定的规则&#xff0c;对其中的数据加以筛选&#xff0c;将不在指定数据范围内的数据剔除&#xff0c;保留符合我们需要的数据的方法。 首先&#xff0c;我们来明确一下本文的具体需求。现有一个Exc…

Centos 7 单机部署 consul

一、下载安装 参考官网文档 Install | Consul | HashiCorp Developer 进入Centos 执行下面命令 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo sudo yum -y install consul 这种方法安装完成…

Javascript简介(全部是基础)

js初识 js是一种解释性语言&#xff0c;不需要编译&#xff0c;直接由浏览器解析执行 组成 ECMAScript是一种开放的&#xff0c;被国际上广为接收的&#xff0c;标准的脚本语言规范&#xff0c;主要描述&#xff1a;语法&#xff0c;变量&#xff0c;数据类型&#xff0c;运算…

什么是DOM?(JavaScript DOM是什么?)

1、DOM简洁 DOM是js中最重要的一部分&#xff0c;没有DOM就不会通过js实现和用户之间的交互。 window是最大的浏览器对象&#xff0c;在它的下面还有很多子对象&#xff0c;我们要学习的DOM就是window对象下面的document对象 DOM&#xff08;Document Object Model&#xff09…

C++ 学习系列 -- std::function 与 std::bind

一 std::function 与 std::bind 的介绍 1. std::function std::function 是 c 11 的新特性 &#xff0c;包含在头文件<functional>中&#xff0c;为了更方便的调用函数而引入。 std::function 是一个函数包装器&#xff08;function wrapper&#xff09;&#xff0c;…

Cmake(1)——Cmake的基本介绍和原理、Cmake的安装、如何使用Cmake构建项目

Cmake的基本介绍和原理、Cmake的安装、如何使用Cmake构建项目 插播&#xff01;插播&#xff01;插播&#xff01;亲爱的朋友们&#xff0c;我们的Cmake课程上线啦&#xff01;感兴趣的小伙伴可以去下面的链接学习哦~ https://edu.csdn.net/course/detail/39261 1、Cmake的基…

在微信公众号中加入ChatGPT聊天的方法

1 介绍 开源项目 "chatgpt-on-wechat" 支持通过微信公众号进行调用&#xff0c;这意味着用户可以在与公众号的交互中体验 ChatGPT。由于服务是部署在远端服务器上的&#xff0c;因此用户只需拥有一部手机&#xff0c;就可以在任何环境下与 ChatGPT 进行交流。例如&am…