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)

大家都在看

  • Go 的 golang.org/x/ 系列包和标准库包有什么区别?

    在开发过程中可能会遇到这样的情况,有一些包是引入自不同地方的,比如: golang.org/x/net/html 和 net/html, golang.org/x/crypto 和…

    Go语言 2023年5月25日
    055
  • 关于Golang的学习路线

    基础 安装golang环境Golang基础,流程控制,函数,方法,面向对象网络编程(自己做一个简单的tcp的聊天室,websocket,http,命令行工具)并发(可以看一下并发爬…

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

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

    Go语言 2023年5月25日
    042
  • go微服务框架Kratos笔记(四)使用nacos作为远端配置中心

    初识nacos nacos是阿里开源的一款用于动态服务发现、配置管理和服务管理的平台。 官方介绍,Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特…

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

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

    Go语言 2023年5月25日
    065
  • go-micro集成RabbitMQ实战和原理

    在go-micro中异步消息的收发是通过Broker这个组件来完成的,底层实现有RabbitMQ、Kafka、Redis等等很多种方式,这篇文章主要介绍go-micro使用Rabb…

    Go语言 2023年5月25日
    053
  • 开源项目|Go 开发的一款分布式唯一 ID 生成系统

    原文连接: 开源项目|Go 开发的一款分布式唯一 ID 生成系统 今天跟大家介绍一个开源项目:id-maker,主要功能是用来在分布式环境下生成唯一 ID。上周停更了一周,也是用来…

    Go语言 2023年5月25日
    057
  • [grpc快速入门] 一 grpc生成与调用

    下载通用编译器 地址:https://github.com/protocolbuffers/protobuf/releases选择对应的版本,解压后将文件夹下bin目录配置到环境变…

    Go语言 2023年5月25日
    063
  • go语言学习笔记-初识Go语言

    Go语言是怎样诞生的? Go语言的创始人有三位,分别是图灵奖获得者、C语法联合发明人、Unix之父肯·汤普森(Ken Thompson)、Plan 9操作系统领导者、UTF-8编码…

    Go语言 2023年5月25日
    064
  • Go sort包

    sort包简介 官方文档Golang的sort包用来排序,二分查找等操作。本文主要介绍sort包里常用的函数,通过实例代码来快速学会使用sort包 sort包内置函数 sort.I…

    Go语言 2023年5月25日
    089
  • Golang Zap日志

    Zap日志解析 Config.yaml zap: level: ‘info’ #日志级别 format: ‘console’ #输出的级别,有console和json prefix…

    Go语言 2023年5月25日
    059
  • 【golang】分布式缓存 – 一致性哈希算法

    之前也了解到过一致性哈希算法,但是没有用go实现过,刚好最近看GeeCache,动手实现下一致性哈希算法 正文: 我们先来想下一致性哈希算法的数据结构含有哪些内容: 1.map 用…

    Go语言 2023年5月25日
    044
  • 【Go实战基础】数组实战,程序员的基本功

    数组实战,程序员的基本功。 实战需求: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。 实战思路: 1、先声明…

    Go语言 2023年5月25日
    026
  • Golang:将日志以Json格式输出到Kafka

    工程实践中,我们往往还需要对日志进行采集,将日志归集到一起,然后用于各种处理分析,比如生产环境上的错误分析、异常告警等等。在日志消息系统领域,Kafka久负盛名,这篇文章就以将日志…

    Go语言 2023年5月25日
    063
  • 使用go语言遇到的一些问题记录

    一、参数校验问题 使用go做web服务时,经常需要对请求参数进行校验,有些必填参数需要校验是否为空。 经常会遇到参数a为int类型,但是其值取值范围为0-xxx。0也是有意义的。 …

    Go语言 2023年5月29日
    052
  • Golang:手撸一个支持六个级别的日志库

    Golang标准日志库提供的日志输出方法有Print、Fatal、Panic等,没有常见的Debug、Info、Error等日志级别,用起来不太顺手。这篇文章就来手撸一个自己的日志…

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