go 中的字符串遍历

首先看下以下例子:

package main

import "fmt"

func main(){

    s := "我是中国人"

 

    for i:=0; i < len(s); i++{

         fmt.Printf("%c", s[i])

    }

 

    fmt.Printf("\n")

 

    for _, v := range s {

        fmt.Printf("%c", v)

    }

 

    fmt.Print("\n")

}

输出结果:

我是中国人

我是中国人


通过len(s)和range遍历访问字符串元素有什么不同么?


首先来复习一下go语言的字符串表示,go语言有以下两种表示字符串的方法:

1、双引号,如:“gogogo\n”,使用转义字符

2、反引号,如:`gogogo\n`,不使用转义字符,字符串的内容将和赋值保持严格一致


在go语言中,没有字符类型,rune就是字符类型


Go 语言中的字符串是以 UTF-8 格式编码并存储的,例如:


s := "Hello 世界!"


  变量 s 中存放的是这个字符串的 UTF-8 编码,当你使用 len(s) 函数获取字符串的长度时,获取的是该字符串的 UTF-8 编码长度。通常我们认为,在电脑中存储一个 ASCII 字符需要一个字节,存储一个非 ASCII 字符需要两个字节,这种认为仅仅是针对 Windows 系统中常用的 ANSI 编码而言的,而在 Go 语言中,使用的是 UTF-8 编码,用 UTF-8 编码来存放一个 ASCII 字符依然只需要一个字节,而存放一个非 ASCII 字符,则需要 2个、3个、4个字节,它是不固定的。


  既然 Go 中的字符串存放的是 UTF-8 编码,那么我们使用 s[0] 这样的下标方式获取到的内容就是 UTF-8 编码中的一个字节。对于非 ASCII 字符而言,这样的一个字节没有实际的意义,除非你想编码或解码 UTF-8 字节流。而在 Go 语言中,已经有很多现成的方法来编码或解码 UTF-8 字节流了。


遍历字符串中的字节(使用下标访问):


func main() {

s := "Hello 世界!"

for i, l := 0, len(s); i < l; i++ {

fmt.Printf("%2v = %v\n", i, s[i]) // 输出单个字节值

}

}


遍历字符串中的字符(使用 for range 语句访问):


func main() {

s := "Hello 世界!"

for i, v := range s { // i 是字符的字节位置,v 是字符的拷贝

fmt.Printf("%2v = %c\n", i, v) // 输出单个字符

}

}

  在 Go 语言中,字符串的内容是不能修改的,也就是说,你不能用 s[0] 这种方式修改字符串中的 UTF-8 编码,如果你一定要修改,那么你可以将字符串的内容复制到一个可写的缓冲区中,然后再进行修改。这样的缓冲区一般是 []byte 或 []rune。如果要对字符串中的字节进行修改,则转换为 []byte 格式,如果要对字符串中的字符进行修改,则转换为 []rune 格式,转换过程会自动复制数据。

修改字符串中的字节(用 []byte):

func main() {

s := "Hello 世界!"

b := []byte(s)        // 转换为 []byte,自动复制数据

b[5] = ','            // 修改 []byte

fmt.Printf("%s\n", s) // s 不能被修改,内容保持不变

fmt.Printf("%s\n", b) // 修改后的数据

}

修改字符串中的字符(用 []rune):

func main() {

s := "Hello 世界!"

r := []rune(s)         // 转换为 []rune,自动复制数据

r[6] = '中'            // 修改 []rune

r[7] = '国'            // 修改 []rune

fmt.Println(s)         // s 不能被修改,内容保持不变

fmt.Println(string(r)) // 转换为字符串,又一次复制数据

}


  在 []byte 中处理 Rune 字符(需要用到 utf8 包中的解码函数)


func main() {

b := []byte("Hello 世界!")

for len(b) > 0 {

r, n := utf8.DecodeRune(b) // 解码 b 中的第一个字符

fmt.Printf("%c\n", r)      // 显示读出的字符

b = b[n:]                  // 丢弃已读取的字符

}

}


本文来自:开源中国博客

感谢作者:ricktian1226

查看原文:go 中的字符串遍历

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。