Go数据类型rune介绍和使用

Go 中比较常见的 int、string、bool、float 基本数据类型之外还有其他的数据类型可以应用在特殊场景,比如 rune 就是类似于 int32,因为其可表示的字符范围更大,实际工作中可以用来计算字符串的真实长度

所属分类 Golang

相关标签 数据字符串类型

关于rune

rune 类型的官方解释如下:

// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune = int32

rune 是 int32 的别名,几乎在所有方面等同于 int32,它用来区分字符值和整数值。

仅仅看这段描述并不能看出 rune 类型的特殊之处。

应用rune

通过一段代码来尝试以下,看看 rune 的特别之处。

func main() {
    str := "米虫 is cool"
    fmt.Println("STR LEN - ", len(str))
}

上文代码中 str 字符串的长度输出会是多少呢?2个汉字2个空格6个字母。

STR LEN -  14

输出的结果并不是预想中的 10 位。

原因是在 Go 中 string 的底层是通过 []byte 来实现的。

其中中文在 Unicode 编码中是占用2个字节,在 utf-8 编码下占用3个字节,因此2个汉字=6个字节,长度为6+2+6=14。

但是如果我们希望获得准确的字符长度呢?总不能自行去判断字符的类型进行加减乘除吧。

第一种方案是,通过 Go 的 RuneCountInString() 函数取得真实的字符串长度。

func main() {
    str := "米虫 is cool"
    fmt.Println("STR LEN - ", utf8.RuneCountInString(str))
}

这个函数内部实际就是遍历整个字符串,判断字符所在的区域从而动态的将指针后跳+1+2+3,最后计算出真实的长度。

emm...虽然是 API 函数,但是总觉得不够优雅。

第二种方案就是通过 []rune 来接收字符串,代码如下:

func main() {
    str := "米虫 is cool"
    fmt.Println("STR LEN - ", len([]rune(str)))
}

可以理解为将 str 转为 []rune 数组,然后计算 []rune 数组的长度即可。

rune和byte

我们前面提到,string 在底层默认通过 []byte,在 Go 中 byte 和 rune 的区别是什么?

// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte = uint8

// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune = int32

rune 和 byte 非常类似,都是可用来表示字符类型的变量类型:

  • byte 等同于 int8,(-128~127)用来表示 ascii 字符,因为 ascii 字符一般就占用一个 byte。
  • rune 等同于 int32,(-2^31~2^31-1)用来表示 unicode 或 utf-8 字符,因为 rune 更大,可能容纳表示更多范围的字符。

因为 byte 数字范围较小,所以用来表示中文字符的时候,utf-8 需要使用3个 byte。

米虫

做一个有理想的米虫,伪全栈程序猿,乐观主义者,坚信一切都是最好的安排!

本站由个人原创、收集或整理,如涉及侵权请联系删除

本站内容支持转发,希望贵方携带转载信息和原文链接

本站具有时效性,不提供有效、可用和准确等相关保证

本站不提供免费技术支持,暂不推荐您使用案例商业化

发表观点

提示

昵称

邮箱

QQ

网址

当前还没有观点发布,欢迎您留下足迹!

同类其他

Golang

Go语言 & 与 * 取值赋值以及函数入参的区别

在 Go 中函数可以接受值传递和指针传递,使用时就涉及到 & 内存地址(指针)与 * 指针赋值的使用,它们的区别是什么?在实际业务使用中,值传递和指针传递的分别应对什么场景需要?针对使用时机进行分析。

GoLand设置gofmt和goimports代码格式化

GoLand 在保存代码时,可以自动调用 gofmt 和 goimports 实现自动格式化代码,在新版本中可以通过 File Watchers 插件来完成这些配置,配置位置位于File

GOPROXY依赖包代理设置

Go1.11版本开始支持包依赖管理工具,新增了GOPROXY环境变量,用于配置依赖包下载代理,通过代理配置可以实现翻墙下载一些所需的依赖包,可以说相当实用

GoLand中旧工程导入飘红处理思路

对于绝大多数新的 Go 项目而言,因为使用 go modules 管理包依赖从而无需要关注工程的目录位置,但是对于一些旧/历史工程在导入 GoLand 之后会出现全面飘红,这个时候就需要逐一排查问题

Go报错xx is shadowed during return

调试 Go 程序报错 xx is shadowed during return,方法在返回的时候不是预期的返回结果,错误的产生应当是在相同作用域中出现了同名的变量导致,根据实际业务场景进行修改

Go中接口的设计与实现

Go语言中的接口采用的是隐式实现,不需要去申明实现,只需要直接实现接口所定义的全部方法即可,同时区分了直接实现与指针实现两种形态,在实际使用时需要注意和关注

选择个人头像

昵称

邮箱

QQ

网址

评论提示

  • 头像:系统为您提供了12个头像自由选择,初次打开随机为你选择一个
  • 邮箱:可选提交邮箱,该信息不会外泄,或将上线管理员回复邮件通知
  • 网址:可选提交网址,评论区该地址将以外链的形式展示在您的昵称上
  • 记忆:浏览器将记忆您已选择或填写过得信息,下次评论无需重复输入
  • 审核:提供一个和谐友善的评论环境,本站所有评论需要经过人工审核