当前位置: 首页 > news >正文

Golang中rune和Byte,字符和字符串有什么不一样

Rune和Byte,字符和字符串有什么不一样

String

Go语言中, string 就是只读的采用 utf8 编码的字节切片(slice) 因此用 len 函数获取到的长度并不是字符个数,而是字节个数。 for循环遍历输出的也是各个字节。

Rune

runeint32 的别名,代表字符的Unicode编码,采用4个字节存储,将 string 转成 rune 就意味着任何一个字符都用4个字节来存储其unicode值,这样每次遍历的时候返回的就是unicode值,而不再是字节了,这样就可以解决乱码问题了

byte

bytes操作的对象也是字节切片,与string的不可变不同,byte是可变的,因此string按增量方式构建字符串会导致多次内存分配和复制,使用bytes就不会因而更高效一点

 

在Go语言中,所谓的RuneByte其实分别就是int32有符号整数类型和uint8无符号整数类型的别称

也就是说

Rune=int32

Byte=unit8

为了理解Rune和Byte的作用,我们必须知道字符和字符串的区别。

字符和字符串的区别在于字符表达的是单一的字母、数字、空格、标点符号而字符串表达的是一个或多个字母、数字、空格和标点符号。和C、Java等语言不同,Go语言中并没有char这个专门用来表示字符的数据类型,而是使用Rune和Byte来表达字符。因此Rune虽然是有符号整数类型的一种,但它通常不用于表示231 到 231-1这些整数,而是用来表示长度可以达到32bit的字符(比如Unicode编码格式的字符),之前我们讲到在对中文字符串做切片时必须将字符串先从默认的8bit的Byte(前面讲到了,在Go中,所谓字符串就是一组字节的切片(slice of bytes))转换成32bit的Rune否则的话会出现乱码就是这个原因,因为汉字通常需要3个字节(24bit)来表示。

而和unit8等价的Byte其实就是我们通常理解的字节,既计算机中最常见的存储单位(1 byte = 8 bits, 1024 bytes = 1 kilobyte, 1024 kilobytes = 1 megabyte…)。和Rune类似,Byte虽然是无符号整数类型的一种,但是它主要的作用并不是用来表示0到255这些整数,而是用来表示长度为8bit的字符。

和用双引号声明的字符串不一样,在Go中我们用单引号来声明一个字符,字符有两种数据类型:Rune和Byte,默认情况下字符的类型为Rune(即隐式声明字符变量时其类型为Rune),举例如下:

func main() {var a rune = 'A'fmt.Println(a)fmt.Printf("%T\n", a)var b = '中'fmt.Println(b)fmt.Printf("%T\n", b)
}

输出:

 

这里我们以显示的方式声明了字符变量a,以隐式的方式声明了字符变量b,此时a和b的类型都为Rune,即int32。

这里你也许会问:为什么我们赋值给变量a的是字符“A”,赋值给变量b的是字符“中”,但变量a和b打印出来的结果却是整数65和20013?这是因为不管是Rune还是Byte,它们的本质还是整数,而字符“A”对应的整数即为65,字符“中”对应的整数即为20013。如果要想将变量a和变量b打印出的内容以原本的字符内容显示,则需要用到格式码%c或者string()函数来将字符转变为字符串,举例如下:

func main() {var a rune = 'A'fmt.Printf("%c\n", a)fmt.Printf("%T\n", a)var b = '中'fmt.Println(string(b))fmt.Printf("%T\n", b)
}

输出:

 

因为默认情况下字符的类型为Rune,如果要创建一个Byte类型的字符变量的话,则必须显示声明变量的类型,举例如下:

func main() {var a byte = 'A'fmt.Printf("%c\n", a)fmt.Printf("%T\n", a)var b byte = '中'fmt.Printf("%c\n", b)fmt.Printf("%T\n", b)
}

 

输出:

这里在运行该程序时出现了“.\integer.go:9:6: constant 20013 overflows byte”的报错,原因也很简单:Byte对应的是无符号整数类型uint8,而uint8的范围是0到255,而字符"中"对应的整数为20013,显然20013不在unit8的范围内,因此会报错。解决的办法就是避免将中文字符赋值以Byte的类型赋值给变量,因为Byte对应的是ASCII编码,而中文对应的是Unicode或UTF-8,需要用到Rune。

最后再强调一次:字符表达的是单一的字母、数字、空格、标点符号,在使用rune或者byte来声明一个字符变量时,如果字符内容里哪怕只多出1个字母、数字、空格、标点符号,那都是无效的字符,Go会返回"more than one character in rune literal"的异常,举例如下:

func main() {var r1 rune = 'a'fmt.Println(string(r1))var r2 rune = 'ab'fmt.Println(string(r2))
}

输出:

 

这里我们分别声明了r1和r2两个rune类型的字符,r1是正常的字符,而r2仅仅因为在字符a后面多加了一个b就导致了Go返回了"more than one character in rune literal"这个异常。

字符串

字符串,可以说是大家很熟悉的数据类型之一。定义方法很简单
var mystr string = "hello"
 

 

上面说的byte 和 rune 都是字符类型,若多个字符放在一起,就组成了字符串,也就是这里要说的 string 类型。

比如 hello ,对照 ascii 编码表,每个字母对应的编号是:104,101,108,108,111

如下示例:

func main() {var mystr01 string = "hello"var mystr02 [5]byte = [5]byte{104, 101, 108, 108, 111}fmt.Printf("mystr01: %s\n", mystr01)fmt.Printf("mystr02: %s", mystr02)
}

输出:

 

mystr01 和 mystr02 输出一样,说明了 string 的本质,其实是一个 byte数组

通过以上学习,我们知道字符分为 byte 和 rune,占用的大小不同。

hello,中国 占用几个字节?

要回答这个问题,你得知道 Go 语言的 string 是用 uft-8 进行编码的,

英文字母占用一个字节,而中文字母占用 3个字节

所以 hello,中国 的长度为 5+1+(3*2)= 12个字节。

func main() {var country string = "hello,中国"fmt.Println(len(country))
}

 输出:

以上虽然我都用双引号表示 一个字符串,但这并不是字符串的唯一表示方式。

除了双引号之外 ,你还可以使用反引号

大多情况下,二者并没有区别,但如果你的字符串中有转义字符\ ,这里就要注意了,它们是有区别的。

使用反引号号包裹的字符串,相当于 Python 中的 raw 字符串,会忽略里面的转义。

比如我想表示 \r\n 这个 字符串,使用双引号是这样写的,这种叫解释型表示法

var mystr01 string = "\\r\\n"

而使用反引号,就方便多了,所见即所得,这种叫原生型表示法

var mystr02 string = `\r\n`

相关文章:

Golang中rune和Byte,字符和字符串有什么不一样

Rune和Byte,字符和字符串有什么不一样 String Go语言中, string 就是只读的采用 utf8 编码的字节切片(slice) 因此用 len 函数获取到的长度并不是字符个数,而是字节个数。 for循环遍历输出的也是各个字节。 Rune rune 是 int32 …...

实施工程师运维工程师面试题

Linux 1.请使用命令行拉取SFTP服务器/data/20221108/123.csv 文件,到本机一/data/20221108目录中。 使用命令行拉取SFTP服务器文件到本机指定目录,可以使用sftp命令。假设SFTP服务器的IP地址为192.168.1.100,用户名为username,密…...

6-13连接两个字符串

#include<stdio.h> int main(){int i0,j0;char s1[222],s2[333];printf("请输入第一个字符串&#xff1a;\n");gets(s1);//scanf("%s",s1);printf("请输入第二个字符串&#xff1a;\n");gets(s2);while(s1[i]!\0)i;while(s2[j]!\0)s1[i]s2…...

Linux中的文件IO

文章目录 C语言文件操作系统文件I/O接口介绍 open函数返回值文件描述符fd0 & 1 & 2文件描述符的分配规则 重定向使用 dup2 系统调用 FILE理解文件系统理解硬链接软链接acm 动态库和静态库静态库与动态库生成静态库生成动态库&#xff1a; C语言文件操作 先来段代码回顾…...

深度学习记录--初识向量化

什么是向量化&#xff1f; 之前计算logistic回归损失函数时&#xff0c;在代码实现时&#xff0c;讨论了for循环&#xff1a;过多的for循环会拖慢计算的速度(尤其当数据量很大时) 因此&#xff0c;为了加快计算&#xff0c;向量化是一种手段 运用python的numpy库&#xff0c…...

树与二叉树堆:经典OJ题集(2)

目录 二叉树的性质及其问题&#xff1a; 二叉树的性质 问题&#xff1a; 一、对称的二叉树&#xff1a; 题目&#xff1a; 解题思路&#xff1a; 二、另一棵树&#xff1a; 题目&#xff1a; 解题思路&#xff1a; 三、翻转二叉树&#xff1a; 题目&#xff1a;…...

Java面试题(每天10题)-------连载(40)

目录 Mysql篇 1、表中有大字段X&#xff08;例如&#xff1a;text类型&#xff09;&#xff0c;且字段X不会经常更新&#xff0c;将该字段拆成子表好处是什么&#xff1f; 2、Mysql中InnoDB引擎的行锁是通过加载什么上完成的&#xff1f; 3、Mysql中控制内存分配的全局参数…...

2023年【起重机司机(限桥式起重机)】报名考试及起重机司机(限桥式起重机)考试资料

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年【起重机司机(限桥式起重机)】报名考试及起重机司机(限桥式起重机)考试资料&#xff0c;包含起重机司机(限桥式起重机)报名考试答案和解析及起重机司机(限桥式起重机)考试资料练习。安全生产模拟考试一点通结合…...

Linux的基本指令(3)

目录 制作小文件&查看 nano指令 cat指令 tac指令 制作大文件&查看 一切皆文件 echo指令 > 输出重定向 以写"w"的形式打开文件 以追加"a"的形式打开文件 cat指令 < 输入重定向 创建big.txt more指令 less指令&#xff08;推…...

C语言memcpy,memmove的介绍及模拟实现

文章目录 每日一言memcpy介绍模拟实现 memmove介绍模拟实现思路代码 结语 每日一言 If you want to lift yourself up, lift up someone else. 如果你想振奋自己&#xff0c; 先振奋周遭的人。 memcpy 介绍 函数原型&#xff1a; void *memcpy(void *dest, const void *sr…...

克服.360勒索病毒:.360勒索病毒的解密和预防

导言: 在数字化的今天&#xff0c;数据安全问题变得愈发棘手。.360勒索病毒是当前网络空间的一场潜在灾难&#xff0c;对于这个威胁&#xff0c;了解应对之道和采取切实的预防措施至关重要。如果您正在经历勒索病毒的困境&#xff0c;欢迎联系我们的vx技术服务号&#xff08;s…...

21、Resnet50 中包含哪些算法?

(本文已加入“计算机视觉入门与调优”专栏,点击专栏查看更多文章信息) 这一节汇总一下resnet50 中包含的算法,并且简单介绍。 总共卷积算法、激活算法(relu)、最大池化算法、加法(主要是为了实现残差结构)、全局平均池化、全连接和 softmax 算法这几种算法。 卷积 卷…...

pybind11教程

pybind11教程 文章目录 pybind11教程1. pybind11简介2. cmake使用pybind11教程3. pybind11的历史 1. pybind11简介 项目的GitHub地址为&#xff1a; pybind11 pybind11 是一个轻量级的头文件库&#xff0c;用于在 Python 和 C 之间进行互操作。它允许 C 代码被 Python 调用&am…...

Java基础- 自定义类加载器

自定义类加载器 在 Java 中实现自定义类加载器通常涉及继承 ClassLoader 类并重写其 findClass 方法。自定义类加载器允许我们从非标准来源&#xff08;如网络、加密文件或其他媒体&#xff09;加载类。下面是实现自定义类加载器的基本步骤&#xff1a; 1. 继承 ClassLoader …...

2022年高校大数据挑战赛A题工业机械设备故障预测求解全过程论文及程序

2022年高校大数据挑战赛 A题 工业机械设备故障预测 原题再现&#xff1a; 制造业是国民经济的主体&#xff0c;近十年来&#xff0c;嫦娥探月、祝融探火、北斗组网&#xff0c;一大批重大标志性创新成果引领中国制造业不断攀上新高度。作为制造业的核心&#xff0c;机械设备在…...

洛谷 P1998 阶乘之和 C++代码

前言 今天我们来做洛谷上的一道题目。 网址&#xff1a;[NOIP1998 普及组] 阶乘之和 - 洛谷 西江月夜行黄沙道中 【宋】 辛弃疾 明月别枝惊鹊&#xff0c;清风半夜鸣蝉。稻花香里说丰年&#xff0c;听取WA声一片。 七八个星天外&#xff0c;两三点雨山前。旧时茅店社林边&…...

洛谷 B2006 地球人口承载力估计 C++代码

目录 前言 思路点拨 AC代码 结尾 前言 今天我们来做洛谷上的一道题目。 网址&#xff1a;地球人口承载力估计 - 洛谷 题目&#xff1a; 思路点拨 经典牛吃草问题。 解设一个人一年吃一份草。 则x*a-y*b为会多出的草&#xff0c;为什么会多呢&#xff1f;是因为每年都有…...

少走弯路:OpenCV、insightface 等多方案人脸推理和识别

脑壳有包又花时间折腾了一下&#xff0c;其实之前也折腾过&#xff0c;主要是新看了一个方法 在下图中查找脸部 第一种方案&#xff1a; 使用了opencv 的cv2.FaceDetectorYN. &#xff0c;完整代码如下&#xff1a; import numpy as np import cv2imgcv2.imread("00000…...

github代码连接vercel 建立一个公用网站

Deploying to the Cloud using Vercel 前置任务 建立一个基于flask的web app代码库并上传至github repo Vercel用途 vercel有点像一个免费的cloud server&#xff0c;帮助你将flask框架下的程序运行在云端。可以public访问。 deploy流程 在主文件夹中建立requirements.tx…...

使用pandas将字符串格式数据转换为单独的行

有时在处理数据时&#xff0c;可能会遇到这样的情况&#xff0c;即数据框中的整个字符串条目需要拆分到不同的行中。这可能是一项具有挑战性的任务&#xff0c;特别是当数据庞大而复杂时。尽管如此&#xff0c;一个名为pandas的Python库提供了各种函数&#xff0c;使用这些函数…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...