一、简介

rune类型是Go语言的一种特殊数字类型。
rune是类型int32的别名,在所有方面都等急啊于它,用来区分字符值跟整数值。
Go语言通过rune处理中文,支持国际化多语言。

字符串由字符组成,字符的底层由字节组成,而一个字符串在底层的表示是一个字节序列。
在 Go 语言中,字符可以被分成两种类型处理:
对占 1 个字节的英文类字符,可以使用byte(或者unit8);
对占 1 ~ 4 个字节的其他字符,可以使用rune(或者int32),如中文、特殊符号等。

二、适用场景

2.1 统计带中文字符串长度

 // 使用内置函数 len() 统计字符串长度fmt.Println(len("Go语言编程"))  // 输出:14

在上面示例中,英文字符占用 1 字节,中文字符占用 3 字节,所以得到的长度 14 显然是底层占用字节长度,而不是字符串长度,这时,便需要用到rune类型。

 // 转换成 rune 数组后统计字符串长度fmt.Println(len([]rune("Go语言编程")))  // 输出:6

更标准的用法:

 // 统计字符串长度fmt.Println(utf8.RuneCountInString("Go语言编程")) // 输出:6

2.2 截取带中文字符串

通常情况下,我们会这么做:

 s := "Go语言编程"// 8=2*1+2*3fmt.Println(s[0:8])  // 输出:Go语言

但按照字节的方式进行截取,必须预先计算出需要截取字符串的字节数,如果字节数计算错误,就会显示乱码,比如这样:

 s := "Go语言编程"fmt.Println(s[0:7]) // 输出:Go语�

此外,如果截取的字符串较长,那通过字节的方式进行截取显然不是一个高效准确的办法。那有没有不用计算字节数,简单又不会出现乱码的方法呢?不妨试试这样:

 s := "Go语言编程"// 转成 rune 数组,需要几个字符,取几个字符fmt.Println(string([]rune(s)[:4])) // 输出:Go语言

三、剖析

Go 语言把字符分byte和rune两种类型处理。
byte是类型unit8的别名,用于存放占 1 字节的 ASCII 字符,如英文字符,返回的是字符原始字节。
rune是类型int32的别名,用于存放多字节字符,如占 3 字节的中文字符,返回的是字符 Unicode 码点值。
如下图所示:

 s := "Go语言编程"// bytefmt.Println([]byte(s)) // 输出:[71 111 232 175 173 232 168 128 231 188 150 231 168 139]// runefmt.Println([]rune(s)) // 输出:[71 111 35821 35328 32534 31243]

对应关系如下图:

3.1 RunCountInString方法源码解析

// RuneCountInString is like RuneCount but its input is a string.
func RuneCountInString(s string) (n int) {// 调用 len() 函数得到字节数ns := len(s)for i := 0; i < ns; n++ {c := s[i]// 如码点值小于 128,则为占 1 字节的 ASCII 字符(或者说英文字符),长度 + 1if c < RuneSelf { // RuneSelf = 128// ASCII fast pathi++continue}// 查询首字节信息表,得到中文占 3 字节,所以这里的 x = 3x := first[c]// 判断 x = 3,xx = 241(0xF1)if x == xx {i++ // invalid.continue}// 提取有效的 UTF-8 字节长度编码信息,size = 3size := int(x & 7)if i+size > ns {i++ // Short or invalid.continue}// 提取有效字节范围accept := acceptRanges[x>>4]// accept.lo,accept.hi,表示 UTF-8 中第二字节的有效范围// locb = 0b10000000,表示 UTF-8 编码非首字节的数值下限// hicb = 0b10111111,表示 UTF-8 编码非首字节的数值上限if c := s[i+1]; c < accept.lo || accept.hi < c {size = 1} else if size == 2 {} else if c := s[i+2]; c < locb || hicb < c {size = 1} else if size == 3 {} else if c := s[i+3]; c < locb || hicb < c {size = 1}i += size}return n
}

调用该函数时,传入一个原始的字符串,代码会根据每个字符的码点大小判断是否为 ASCII 字符,如果是,则算做 1 位;如果不是,则查询首字节表,明确字符占用的字节数,验证有效性后再进行计数。

四、参考

[1]. 解析Go中的rune类型

go - rune类型相关推荐

  1. golang rune类型简介

    定义 rune关键字,它是int32的别名(-231~231-1),对于byte(-128-127),可表示的字符更多. 官方的解释如下: // rune is an alias for int32 ...

  2. go语言的rune类型

    在学习golang基础的时候,发现有个叫rune的的数据类型,当时不理解这个类型的意义. 查询,官方的解释如下: // rune is an alias for int32 and is equiva ...

  3. bool类型数组转换成一个整数_Go 学习笔记 02 | 基本数据类型以及 byte 和 rune 类型...

    一.基本数据类型 unsafe.Sizeof() 查看不同长度的整型在内存中的存储空间. 类型转换,高位向低位转换要注意溢出. 数字字面量语法. 64 位系统中 Go 语言中浮点数默认是 float6 ...

  4. golang中的rune类型

    前言 在学习golang基础的时候,发现有个叫rune的的数据类型,因为本人之前一直学习的是Java相关的知识,这里对于golang里面的rune类型确实感到很不理解.因此,特写这篇文章一探究竟. 正 ...

  5. Go中rune类型浅析

  6. golang:字符类型(byte和rune)

    字符串中的每一个元素叫做"字符",在遍历或者单个获取字符串元素时可以获得字符 golang语言的字符有如下两种: 一种是uint8 类型,或者叫 byte 型,代表了 ASCII ...

  7. Go 学习笔记(31)— 字符串 string、字符 rune、字节 byte、UTF-8 和 Unicode 区别以及获取字符串长度

    1. 字符串 string 类型 Go 语言中字符串的内部实现使用 UTF-8 编码,通过 rune 类型,可以方便地对每个 UTF-8 字符进行访问.当然, Go 语言也支持按照传统的 ASCII ...

  8. Go 学习笔记(4)— Go 标识符、数据类型之间转换、布尔型、整型、浮点型、interface 类型

    1. 标识符整体分类 Go 标识符整体分类如下图所示: 2. 数据类型分类 Go 语言按类别有以下几种数据类型: 类型 描述 布尔型 布尔型的值只可以是常量 true 或者 false 数字类型 整型 ...

  9. golang中的byte与rune

    byte与rune byte与rune类型有一个共性,即:它们都属于别名类型.byte是uint8的别名类型,而rune则是int32的别名类型. byte类型的值需用8个比特位表示,其表示法与uin ...

最新文章

  1. C++泛型编程:template模板
  2. 全国大学生智能汽车竞赛-讯飞赛道规则解读
  3. oracle 学习笔记之触发器
  4. 使用xib封装一个view的步骤
  5. MATLAB调用python文件方法
  6. 通用的异步处理类和进度通知类及其示例
  7. TTButton 的正确使用的方法
  8. 正确配置Linux系统ulimit/nproc值的方法
  9. 结构方程软件Lisrel 8.7 和HLM5.5
  10. 小米笔记本电脑键盘卡键维修
  11. 数学建模国奖论文2019-C-C308分析
  12. UEFI学习——在qemu上读取设备PCI信息
  13. 云服务器搭建java服务器运行环境
  14. 使用支付宝小程序input组件的坑
  15. 奇怪的问题:Windows 11 22H2任务管理器颠倒显示GPU使用率
  16. 记一次对网络抖动经典案例的分析
  17. (十三)office2016-excel提取出生年月
  18. 黑视素照度(EML) Equivalent Melanopic Lux 计算工具
  19. 重庆华南城开业运营发布会暨华南城APP上线仪式圆满成功
  20. grep命令_Linux grep命令

热门文章

  1. linux最新内核4.19,Linux Kernel 4.19发布,初步支持Wi-Fi 6, 新EROFS文件系统
  2. 美众议院拟立法暂停美债上限
  3. 软件实施实习生应该学什么?
  4. 前端CSS学习之路-css002
  5. html js 在线预览 pdf word xls等
  6. 没人谈论的 3 种从 ChatGPT 赚钱的方法,我测试过的建立被动收入流的行之有效的方法
  7. 英汉小字典java_java 学习案例之英汉字典
  8. 该如何选择Java开发和嵌入式开发
  9. ERROR in [copy-webpack-plugin] unable to locate ‘./src/lib/map‘ at ‘C:\Users\1\Desktop\node\lgx\src\
  10. paper_summary