Go语言rune类型如何深入理解?

2026-05-05 22:212阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1037个文字,预计阅读时间需要5分钟。

Go语言rune类型如何深入理解?

1. 字符串简单遍历操作 + 在许多语言中,字符串都是不可变类型,golang 也是如此。

2.访问字符串字符 + 以下代码可以实现访问字符串的每个字符:

go package main import fmt // 字符串每个字符

一、字符串简单遍历操作

在很多语言中,字符串都是不可变类型,golang也是。

1、访问字符串字符

如下代码,可以实现访问字符串的单个字符和单个字节

package main import ( "fmt" ) // 字符串每个字节十六进制打印 func printBytes(s string){ fmt.Printf("Bytes: ") for i := 0; i < len(s); i++{ fmt.Printf("%x ", s[i]) } fmt.Printf("\n") } // 打印字符串的每一个字符 func printChars(s string) { fmt.Printf("Charaters: ") for i := 0; i < len(s); i++{ fmt.Printf("%c ", s[i]) } fmt.Printf("\n") } func main(){ var s1 = "golang" fmt.Printf("s1: %s, len(s1)=%d\n", s1, len(s1)) printBytes(s1) printChars(s1) }

执行结果为:

s1: golang, len(s1)=6 Bytes: 67 6f 6c 61 6e 67 Charaters: g o l a n g

字符串golang长度为6,%x按照十六进制格式输出每一个字符的ASCII码,%c对应格式输出每一个字符。

2、查看中文字符存在问题

上述代码针对字符串s1=golang没有异常,看起来实现的两个函数也是访问字符串单个字符的合法方式,但这有一个严重的错误。上面的程序没有考虑字符串中一个字符占多字节的情况,例如 中文字符。来看下面代码:

package main import ( "fmt" ) // 字符串每个字节十六进制打印 func printBytes(s string){ fmt.Printf("Bytes: ") for i := 0; i < len(s); i++{ fmt.Printf("%x ", s[i]) } fmt.Printf("\n") } // 打印字符串的每一个字符 func printChars(s string) { fmt.Printf("Charaters: ") for i := 0; i < len(s); i++{ fmt.Printf("%c ", s[i]) } fmt.Printf("\n") } func main(){ var s2 = "Go编程" fmt.Printf("s2: %s, len(s1)=%d\n", s2, len(s2)) printBytes(s2) printChars(s2) }

执行结果为:

s2: Go编程, len(s1)=8 Bytes: 47 6f e7 bc 96 e7 a8 8b Charaters: G o ç ¼ * _ ^ ~

按照想法,应该正常打印出Charaters: G o 编 程的字符,但是输出Charaters: G o ç ¼ *乱码,而明显的长度应该为4,这里显示len(s1)=8,长度为8。

3、原因

golang中string底层是通过byte数组实现的,所以直接求len,实际是在按字节长度计算。中文字符在unicode下占2个字节,在utf-8编码下占3个字节,而golang默认编码正好是utf-8。所以一个汉字占3个字节算了3个长度。所以打印长度为8=2(Go)+3(编)+3(程)。

二、rune类型 1、使用rune类型遍历字符

如何按照预期一个包含中文字符的字符串长度,而非字节长度?代码如下:

package main import ( "fmt" "unicode/utf8" ) func printChars(s string) { fmt.Printf("Characters: ") runes := []rune(s) for i := 0; i < len(runes); i++ { fmt.Printf("%c ", runes[i]) } } func main() { var s = "Go编程" fmt.Println("s :", s) // 输出字符占用字节个数 fmt.Println("len(s):", len(s)) // 方案一 //golang中的unicode/utf8包提供了用utf-8获取长度的方法 fmt.Println("RuneCountInString:", utf8.RuneCountInString(str)) //方案二 //通过rune类型处理unicode字符 fmt.Println("rune:", len([]rune(str))) printBytes(s) }

执行结果:

s: Go编程 len(s): 8 RuneCountInString: 4 rune: 4 Characters: Go编程

可以通过rune类型转换可以正常输出每个中文字符,包括字符串中的字符个数。

说明:golang中rune是内置类型,是int32类型的别名,而byte数据类型等同于int8类型

  • byte常用来处理ascii字符
  • rune可以处理utf-8字符
2、 获取字节下标

为了更进一步看清楚每个字符占用的字节数,查看字符串中字符的字节下标

package main import ( "fmt" ) func charsIndex(s string) { for index, r := range s { fmt.Printf("字符 %c 从第 %d 个字节开始\n", r, index) } } func main() { s := "Go编程" fmt.Println("s: ", s) fmt.Println("len rune:", len([]rune(s))) charsIndex(s) }

执行结果如下

Go语言rune类型如何深入理解?

s: Go编程 len rune: 4 字符 G 从第 0 个字节开始 字符 o 从第 1 个字节开始 字符 编 从第 2 个字节开始 字符 程 从第 5 个字节开始

从上面输出可以看到,在utf-8编码下,每个英文字符占用1个字节,中文字符占用3个字节。

本文共计1037个文字,预计阅读时间需要5分钟。

Go语言rune类型如何深入理解?

1. 字符串简单遍历操作 + 在许多语言中,字符串都是不可变类型,golang 也是如此。

2.访问字符串字符 + 以下代码可以实现访问字符串的每个字符:

go package main import fmt // 字符串每个字符

一、字符串简单遍历操作

在很多语言中,字符串都是不可变类型,golang也是。

1、访问字符串字符

如下代码,可以实现访问字符串的单个字符和单个字节

package main import ( "fmt" ) // 字符串每个字节十六进制打印 func printBytes(s string){ fmt.Printf("Bytes: ") for i := 0; i < len(s); i++{ fmt.Printf("%x ", s[i]) } fmt.Printf("\n") } // 打印字符串的每一个字符 func printChars(s string) { fmt.Printf("Charaters: ") for i := 0; i < len(s); i++{ fmt.Printf("%c ", s[i]) } fmt.Printf("\n") } func main(){ var s1 = "golang" fmt.Printf("s1: %s, len(s1)=%d\n", s1, len(s1)) printBytes(s1) printChars(s1) }

执行结果为:

s1: golang, len(s1)=6 Bytes: 67 6f 6c 61 6e 67 Charaters: g o l a n g

字符串golang长度为6,%x按照十六进制格式输出每一个字符的ASCII码,%c对应格式输出每一个字符。

2、查看中文字符存在问题

上述代码针对字符串s1=golang没有异常,看起来实现的两个函数也是访问字符串单个字符的合法方式,但这有一个严重的错误。上面的程序没有考虑字符串中一个字符占多字节的情况,例如 中文字符。来看下面代码:

package main import ( "fmt" ) // 字符串每个字节十六进制打印 func printBytes(s string){ fmt.Printf("Bytes: ") for i := 0; i < len(s); i++{ fmt.Printf("%x ", s[i]) } fmt.Printf("\n") } // 打印字符串的每一个字符 func printChars(s string) { fmt.Printf("Charaters: ") for i := 0; i < len(s); i++{ fmt.Printf("%c ", s[i]) } fmt.Printf("\n") } func main(){ var s2 = "Go编程" fmt.Printf("s2: %s, len(s1)=%d\n", s2, len(s2)) printBytes(s2) printChars(s2) }

执行结果为:

s2: Go编程, len(s1)=8 Bytes: 47 6f e7 bc 96 e7 a8 8b Charaters: G o ç ¼ * _ ^ ~

按照想法,应该正常打印出Charaters: G o 编 程的字符,但是输出Charaters: G o ç ¼ *乱码,而明显的长度应该为4,这里显示len(s1)=8,长度为8。

3、原因

golang中string底层是通过byte数组实现的,所以直接求len,实际是在按字节长度计算。中文字符在unicode下占2个字节,在utf-8编码下占3个字节,而golang默认编码正好是utf-8。所以一个汉字占3个字节算了3个长度。所以打印长度为8=2(Go)+3(编)+3(程)。

二、rune类型 1、使用rune类型遍历字符

如何按照预期一个包含中文字符的字符串长度,而非字节长度?代码如下:

package main import ( "fmt" "unicode/utf8" ) func printChars(s string) { fmt.Printf("Characters: ") runes := []rune(s) for i := 0; i < len(runes); i++ { fmt.Printf("%c ", runes[i]) } } func main() { var s = "Go编程" fmt.Println("s :", s) // 输出字符占用字节个数 fmt.Println("len(s):", len(s)) // 方案一 //golang中的unicode/utf8包提供了用utf-8获取长度的方法 fmt.Println("RuneCountInString:", utf8.RuneCountInString(str)) //方案二 //通过rune类型处理unicode字符 fmt.Println("rune:", len([]rune(str))) printBytes(s) }

执行结果:

s: Go编程 len(s): 8 RuneCountInString: 4 rune: 4 Characters: Go编程

可以通过rune类型转换可以正常输出每个中文字符,包括字符串中的字符个数。

说明:golang中rune是内置类型,是int32类型的别名,而byte数据类型等同于int8类型

  • byte常用来处理ascii字符
  • rune可以处理utf-8字符
2、 获取字节下标

为了更进一步看清楚每个字符占用的字节数,查看字符串中字符的字节下标

package main import ( "fmt" ) func charsIndex(s string) { for index, r := range s { fmt.Printf("字符 %c 从第 %d 个字节开始\n", r, index) } } func main() { s := "Go编程" fmt.Println("s: ", s) fmt.Println("len rune:", len([]rune(s))) charsIndex(s) }

执行结果如下

Go语言rune类型如何深入理解?

s: Go编程 len rune: 4 字符 G 从第 0 个字节开始 字符 o 从第 1 个字节开始 字符 编 从第 2 个字节开始 字符 程 从第 5 个字节开始

从上面输出可以看到,在utf-8编码下,每个英文字符占用1个字节,中文字符占用3个字节。