Go 中的 byte、rune 与 string

byte 和 rune

byte 是 uint8 的别名,其字面量是 8 位整数值,byte 切片相比于不可变的 string 方便常用许多。它可以更改每个字节或字符。这对于处理文件内容(无论是文本文件、二进制文件还是来自网络的I/O流)非常有效。byte 切片是一个可变的字节序列

rune 是 int32 的别名,其字面量是 32 位整数值,用来表示 Unicode 字符编码。rune 类似于 byte,不同点在于 rune 每个索引是一个字符而不是一个字节。rune 切片是对字节片的重新分组使得每个索引都是一个字符。

如果你处理的文本文件有很多非 ascii 字符,比如中文文本、数学公式或带有表情符号的文本,使用 rune 是最好的。

rune 也是从字符串中获取子字符串的理想选择。它支持 Unicode 字符,没有数据损坏的风险。

对于 []rune,len()和索引都是基于 rune(int32)的。
当你将 []rune 转换为 string 时,每个 rune 成为字符串中的一个 utf-8 字符。

byte 和 rune 的区别

func main() {
    s := "GÖ"
    sample := "H哈"

    sByte := []byte(s)
    sRune := []rune(s)
    sampleByte := []byte(sample)
    sampleRune := []rune(sample)

    fmt.Printf("%s\nsByte: %d\nsRune: %d\n", s, sByte, sRune)
    fmt.Println("------")
    fmt.Printf("%s\nsampleByte: %d\nsampleRune: %d\n", sample, sampleByte, sampleRune)
}

可以看到rune 中非 ASCII 码字符的 Unicode 编码为 1-3 字节,与 ASCII 码字符的字节数不一定相同。

string

string 是不可变的 byte 切片。因为Go中的源代码使用 utf-8 编码,因此每个字符串也使用utf-8编码,即 string 字面量是 utf-8 编码,以 byte 为单位的。string 中的每个字符实际占用 1-3 个字节,而每个 rune 占 4 个字节。

  • 使用 rune() 可把 byte 为单位的字符转换为 rune 字符,对于 ASCII 字符来说,rune 值和 byte 值相同,而对于 Unicode 编码的字符来说便不同了。
  • 使用 []rune() 将 string 转换 rune 数组。当将字符串转换为 rune 切片时,字符串中的每个 utf-8 字符被转换为一个 rune,从而获得包含字符串 Unicode 编码字符的新切片。
  • 对于 string,len()和索引都是基于 byte(unint8)的
  • 在 Go 中将字符串转换为 rune 切片是一个标准操作,没有数据损坏的风险。
    字符串是处理短字节或字符序列的好方法。每次对字符串进行操作(如查找替换字符串或接受子字符串)时,都会创建一个新字符串。如果字符串非常大,比如文件的内容,效率就会非常低。
    [En]

    Strings are a good way to deal with short bytes or character sequences. Each time you operate on a string, such as finding a replacement string or accepting a substring, a new string is created. If the string is very large, such as the contents of the file, it is very inefficient.

例如我们先看下面程序:

func main() {

    sample := "Hel哈"
    for i := 0; i < len(sample); i++ {
        fmt.Print(sample[i], " ")
    }
    fmt.Println()
    fmt.Printf("%s\t的字节长度: %d\n", sample, len(sample))
    fmt.Printf("哈\t字符的字节长度: %d\n", utf8.RuneLen('哈'))
    fmt.Printf("%s\t的字符长度: %d\n", sample, utf8.RuneCountInString(sample))
}

输出:

72 101 108 229 147 136
Hel哈   的字节长度: 6
哈      字符的字节长度: 3
Hel哈   的字符长度: 4

可以看出字符串的长度(len)和字符串的字符长度(RuneCountInString)是不同的。因为字符串是字节切片,Go 默认 UTF-8,存储非 ASCII 字符时,每个字符则会存储 1-3 个字节。所以想要正确地索引字符串中的字符有以下两种方法:

关于编码的一些方法

utf8.ValidRune(chr) 判断 chr 是否可以编码为合法的utf-8序列。
utf8.RuneLen(chr) 查看字符 chr 的字节长度
utf8.RuneCount() 查看字节数组中按照 rune 单位的字符长度
utf8.RuneCountInString 查看字符串按照 rune 单位的长度

参考资料

Original: https://www.cnblogs.com/vio1etus/p/go-zhong-de-byterune-yu-string.html
Author: vio1etus
Title: Go 中的 byte、rune 与 string

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/514946/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 写了一年golang,来聊聊进程、线程与协程

    本文已收录 https://github.com/lkxiaolou/lkxiaolou 欢迎star。 进程 在早期的单任务计算机中,用户一次只能提交一个作业,独享系统的全部资源…

    Go语言 2023年5月25日
    068
  • Golang开源流媒体服务器(RTMP/RTSP/HLS/FLV等协议)

    一. lal 简介 lal是开源直播流媒体网络传输项目,主要由三部分组成: lalserver:流媒体转发服务器。类似于 nginx-rtmp-module等服务,但支持更多的协议…

    Go语言 2023年5月25日
    058
  • Go 简单入门

    GO的环境配置? GOPATH GOROOT 都是干嘛用的? 配置环境跟java对比有点奇怪 https://blog.csdn.net/weixin_40563757/artic…

    Go语言 2023年5月25日
    065
  • Go语言实现大数开方程序

    Go语言的big包实现大数运算,但是有关大整数运算,似乎没有相应的开方程序。 这里给出的程序,实现了大整数的开方运算函数。该程序是基于大整数开方运算的算法实现的。 Go语言程序: …

    Go语言 2023年5月29日
    051
  • Go语言 异常panic和恢复recover用法

    背景:Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会…

    Go语言 2023年5月29日
    043
  • go 自定义http.Client – 动态修改请求Body

    在对接Alexa Smart Home时,有的请求Payload中需要传入Access Token,但是这个Token是由OAuth2 Client管理的,封装Payload时并不…

    Go语言 2023年5月25日
    044
  • go程序添加远程调用tcpdump功能

    最近开发的telemetry采集系统上线了。听起来高大上,简单来说就是一个grpc/udp服务端,用户的机器(路由器、交换机)将它们的各种统计数据上报采集、整理后交后端的各类AI分…

    Go语言 2023年5月25日
    052
  • Operator 示例:使用 Redis 部署 PHP 留言板应用程序

    安装 Docker Desktop,并启动内置的 Kubernetes 集群 注册一个hub.docker.com 账户,需要将本地构建好的镜像推送至公开仓库中 安装 operat…

    Go语言 2023年5月25日
    059
  • Golang的JWT权限校验解析

    JWT校验 配置文件 package config type JWT struct { SigningKey string json:"signingKey" …

    Go语言 2023年5月25日
    057
  • Go语言之变量与基础数据类型

    Go 是静态(编译型)语言,是区别于解释型语言的弱类型语言(静态:类型固定,强类型:不同类型不允许直接运算) 例如 python 就是动态强类型语言 1、Go 的特性: 跨平台的编…

    Go语言 2023年5月25日
    044
  • 一次不规范HTTP请求引发的nginx响应400问题分析与解决

    背景 最近分析数据偶然发现nginx log中有一批用户所有的HTTP POST log上报请求均返回400,没有任何200成功记录,由于只占整体请求的不到0.5%,所以之前也一直…

    Go语言 2023年5月25日
    075
  • [原创]Golang一行代码给钉钉群推送消息

    [原创]Golang一行代码给钉钉群推送消息 钉钉本来就是工具,只是boss把你变成了工具. — 麦·卡隆 今天朋友扔给我个某签到脚本,让我做推送功能. 我迅速从吃灰收藏夹里掏出S…

    Go语言 2023年5月25日
    037
  • 惨,给Go提的代码被批麻了

    hello大家好,我是小楼。 不知道大家还记不记得我上次找到了一个Go的Benchmark执行会超时的Bug?就是这篇文章《我好像发现了一个Go的Bug?》。 之后我就向Go提交了…

    Go语言 2023年5月25日
    065
  • GO环境配置

    一、环境安装及配置 引用链接:Go语言环境安装及配置 Go版本安装 百度网盘msi地址:版本v1.18.1提取码:m1mc GoLand工具 链接:【版本2020.1】提取码:7x…

    Go语言 2023年5月25日
    065
  • Go语言之反射

    一、反射的基本概念 (一)什么是反射 反射可以再运行时动态获取变量的各种信息,比如变量的类型、值等 如果时结构体变量,还可以获取到结构体本身的各种信息,比如结构体的字段、方法 通过…

    Go语言 2023年5月29日
    063
  • EbitenCookBook中文教程 第一课:安装 Ebiten

    本文实时更新原址:https://ebitencookbook.vercel.app/docs/CookBook_Start/class1 第一课 安装 Ebiten 欢迎大家来到…

    Go语言 2023年5月25日
    046
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球