zoukankan      html  css  js  c++  java
  • Go 语言中的 byte 类型和 rune 类型

    Go 语言中定义字符串要用双引号,而不是单引号,单引号中只能包含一个元素,表示一个字符。

    Go语言中字符有两种类型,分别是:

    1. uint8 类型,或者叫 byte 型,代表了 ASCII 码的一个字符
    2. rune 类型,代表一个 UTF-8 字符

    了解编码知识的应该知道,ASCII 编码字符是1个字节的,而 UTF-8 是可变长的编码,当要表示中文等非 ASCll 编码的字符时,需要使用 UTF-8 编码来保证不会乱码。关于字符编码相关知识,推荐看这篇廖雪峰的介绍 字符编码

    假如我们要遍历输出一个包含中文的字符串时:

    package main
    
    import "fmt"
    
    func main() {
    	str := "hello 世界"
    	for i := 0; i < len(str); i++ {
    		fmt.Println(str[i])
    	}
    }
    

    上述代码的打印结果是:

    104
    101
    108
    108
    111
    32
    228
    184
    150
    231
    149
    140
    

    Go 语言字符串存储的其实是类型为 byte 的只读切片,或者说一个字符串就是一堆字节。在 UTF-8 编码中一个英文字符可以用一个字节存储,一个中文字符需要三个或四个字节存储,而 ASCII 码符号只有 128 个,大于 128 的都不在范围内。上述代码的遍历方式就是以 ASCII 类型来读字符的。

    可以看到输出结果中的前 6 个都是在 ASCII 表中的,但是后 6 个就不在表中了,后面 6 个的每一个字节都不能单独表示一个字符,而是用 3 个在一起才能表示一个字符,明显超出了 ASCII 表的范围,所以当打印具体字符时就会乱码,比如我们现在来打印每一个真实字符,需要使用到占位符 %c

    package main
    
    import "fmt"
    
    func main() {
    	str := "hello 世界"
    	for i := 0; i < len(str); i++ {
    		fmt.Printf("%c", str[i]) // hello ä¸ç
    	}
    }
    

    输出结果为:

    hello ä¸ç
    

    明显乱码了。解释这么多就是为了说明如果字符串中有非 ASCII 码的字符时,就不能使用 byte 来表示字符,需要使用 rune 类型来表示。

    使用 rune 类型来遍历字符串

    在 Go 中,有一个遍历方式是 range,它默认就是以 UTF-8 编码形式去读每一个字符。当涉及到的字符串中含有非英文字符时,可以使用 range 来遍历:

    package main
    
    import "fmt"
    
    func main() {
    	str := "hello 世界"
    	for _, r := range str {
    		fmt.Println(r)
    	}
    }
    

    输出结果为:

    104
    101
    108
    108
    111
    32
    19990
    30028
    

    此时输出的字节编码就是 UTF-8 编码号,UTF-8 编码是包含 ASCII 编码的,所以前 6 个编号还是一样的,后面两个编号分别代表

    修改字符串

    Go 语言中对字符串的修改其实不是对字符串本身的修改,而是复制字符串,同时修改值,即重新分配来内存,需要先将字符串转化成数组,[]byte[]rune,然后再转换成 string 型。

    那么我要说的也很明显了,就是要区别使用 []byte[]rune

    对于全是ASCII编码的字符串,使用 []byte 即可:

    package main
    
    import "fmt"
    
    func main() {
    	str := "abc"
    	s2 := []byte(str)
    	s2[0] = 'b'
    	fmt.Println(string(s2)) //bbc
    }
    
    // string()表示强制类型转换,转换为字符串
    

    对于包含中文等字符的字符串时,那就要用 []rune 了:

    func main() {
        str:="白猫"
        s2:=[]rune(str)
        s2[0]='黑'
        fmt.Println(string(s2)) //黑猫
    }
    

    总结

    在处理字符时,要考虑字符的编码范围,然后根据需要使用 byte 类型或 rune类型。

    byte 类型只能正常输出 ASCII 编码范围的字符;rune 类型可以输出 UTF-8 编码范围的字符。

  • 相关阅读:
    SQL Server将一列的多行内容拼接成一行的问题讨论
    SQL 获取 IDENTITY 三种方法 SCOPE_IDENTITY、IDENT_CURRENT 和 @@IDENTITY的区别
    构建高性能服务(二)
    乐观锁解决高并发
    c#问答篇:对象与引用变量-----初学者的困惑
    vs调试 本地IIS
    【转】android adb常用指令
    【转】使用 JMeter 完成常用的压力测试
    【转】利用 Apache JMeter 测试 WebSphere 性能
    【转】用JMeter来测试Tomcat的性能
  • 原文地址:https://www.cnblogs.com/wjaaron/p/14822799.html
Copyright © 2011-2022 走看看