Go的字符串遍历,有两种方式:
- utf-8遍历
- unicode遍历
package main import "fmt" func main() { str := "Hello,世界" fmt.Println("Utf-8遍历") for i := 0; i < len(str); i++ { ch := str[i] fmt.Println(ch) } fmt.Println("Unicode遍历") for _, ch1 := range str { fmt.Println(ch1) } }
打印结果:
Utf-8遍历 72 101 108 108 111 44 228 184 150 231 149 140 Unicode遍历 72 101 108 108 111 44 19990 30028
上面代码执行后,会打印一串数字而不是字符。这是由于go语言中的字符串实际上是类型为byte的只读切片。或者说一个字符串就是一堆字节。这意味着,当我们将字符存储在字符串中时,实际存储的是这个字符的字节。一个字符串包含了任意个byte,它并不限定Unicode,UTF-8或者任何其他预定义的编码。
那么go语言用什么来表示字符呢,下面的例子可以验证一下:
package main import ( "fmt" "reflect" ) func main() { str := "Hello,世界" fmt.Println("Utf-8遍历") for i := 0; i < len(str); i++ { ch := str[i] ctype:=reflect.TypeOf(ch) fmt.Printf("%s ",ctype) } fmt.Println("Unicode遍历") for _, ch1 := range str { ctype:=reflect.TypeOf(ch1) fmt.Printf("%s ",ctype) } }
打印结果:
Utf-8遍历 uint8 uint8 uint8 uint8 uint8 uint8 uint8 uint8 uint8 uint8 uint8 uint8 Unicode遍历 int32 int32 int32 int32 int32 int32 int32 int32
代码运行后显示ch的类型为uint8,也就是byte类型,而ch1的类型为int32,也就是rune类型。
go语言中的源码定义为utf-8文本,不允许其他的表示。
但是也存在特殊处理,那就是字符串上使用for…range循环。
range循环迭代时,就会解码一个utf-8编码的rune。
现在既然已经知道上述不管哪种遍历方式,其实质都是字节。
所以在打印时,只需要将这些结果转化为字符字面值或者转换其输出类型就可以了。
下面是两种字符串遍历方式:
package main import ( "fmt" ) func main() { str := "Hello,世界" fmt.Println("方法一 格式化打印") for _, ch1 := range str { fmt.Printf("%q",ch1) //单引号围绕的字符字面值,由go语法安全的转义 } fmt.Println("方法二 转化输出格式") for _, ch2 := range str { fmt.Println(string(ch2)) } }
打印结果:
方法一 格式化打印 'H''e''l''l''o'',''世''界'
方法二 转化输出格式 H e l l o , 世 界