美文网首页
【Go基础】字符类型

【Go基础】字符类型

作者: abboo | 来源:发表于2020-10-25 15:54 被阅读0次

    rune类型

    Go语言的字符有以下两种:
    一种是 uint8 类型,或者叫 byte 型,代表了 ASCII 码的一个字符。
    另一种是 rune 类型,代表一个 UTF-8 字符,当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。rune 类型等价于 int32 类型。

    byte 类型是 uint8 的别名,对于只占用 1 个字节的传统 ASCII 编码的字符来说,完全没有问题,例如 var ch byte = 'A',字符使用单引号括起来。

    Go语言同样支持 Unicode(UTF-8),因此字符同样称为 Unicode 代码点或者 runes,并在内存中使用 int 来表示。在文档中,一般使用格式 U+hhhh 来表示,其中 h 表示一个 16 进制数。

    在书写 Unicode 字符时,需要在 16 进制数之前加上前缀\u或者\U。因为 Unicode 至少占用 2 个字节,所以我们使用 int16 或者 int 类型来表示。如果需要使用到 4 字节,则使用\u前缀,如果需要使用到 8 个字节,则使用\U前缀。

    Unicode 包中内置了一些用于测试字符的函数,这些函数的返回值都是一个布尔值,如下所示(其中 ch 代表字符):
    判断是否为字母:unicode.IsLetter(ch)
    判断是否为数字:unicode.IsDigit(ch)
    判断是否为空白符号:unicode.IsSpace(ch)

    双引号和单引号

    单引号

    v := 'n' // 修改这里!
    fmt.Printf("v is of type %T\n", v) //v is of type int32
    

    输出单引号的变量,发现其类型是int32。
    go语言使用一个特殊类型 rune 表示字符型。rune 为 int32 的别名,它完全等价于 int32,习惯上用它来区别字符值和整数值。rune 表示字符的 Unicode 码值。
    双引号
    Go中,双引号是用来表示字符串string,其实质是一个byte类型的数组。
    Go中字符串是一个不可变的值类型,内部用指针指向UTF-8字节数组。因此可以用索引号访问某字节,也可以用len()函数来获取字符串所占的字节长度。例如:

        s := "hello 世界"  
        fmt.Println(s[0])   //104
        fmt.Println(len(s)) //12
        fmt.Println(s)      //hello 世界
        fmt.Println(reflect.TypeOf(s[0]))//uint8 
        fmt.Println(string(s[0]))   //h
    

    第一个语句会打印数字而不是字符。这是由于go语言中的字符串实际上是类型为byte的只读切片。或者说一个字符串就是一堆字节。这意味着,当我们将字符存储在字符串中时,实际存储的是这个字符的字节。一个字符串包含了任意个byte,它并不限定Unicode,UTF-8或者任何其他预定义的编码。因为遍历字符串有时候可以是utf-8的编码(下面会讲到)。

    在这里s[0]类型为uint8,也就是byte类型。
    len(s)结果为12,因为golang中string底层是通过byte数组实现的。中文字符在unicode下占2个字节,在utf-8编码下占3个字节,而golang默认编码正好是utf-8。
    因此 len(s)=6+2*3=12,len(s)获取的是底层字节码长度

    那么?如果我们预期想得到一个字符串的长度,而不是字符串底层占得字节长度,该怎么办呢???

    1. 引入"unicode/utf8"包
        //golang中的unicode/utf8包提供了用utf-8获取长度的方法
        fmt.Println("RuneCountInString:", utf8.RuneCountInString(s))
    
    1. 通过rune类型处理unicode字符,类型强转
        //通过rune类型处理unicode字符
        fmt.Println("rune:", len([]rune(s)))
    

    反引号
    反引号用来创建原生的字符串字面量 ,这些字符串可能由多行组成,不支持任何转义序列。原生的字符串字面量多用于书写多行消息、HTML 以及正则表达式。

    str := `hello\n世界
    我是 abboo`
        fmt.Println(str)
    /*
    hello\n世界
    我是 abboo
    */
    

    会将字符串的全部输出,你看到是什么就是什么

    强类型

    go是强类型语言,因此,当把两个不同类型的变量进行拼接时,就会报错。

    字符串拼接

    有时使用 fmt.Printf() 输出时,由于格式化字符串太长,想分多行书写,但是又不想引入换行。此时就可以将多行的字符串使用运算符 + 拼接在一起。

    字符串拼接符+。在实际使用时还需要注意,当拼接的字符串位于不同行时,拼接符需要放在上一行的末尾,这是因为编译器会进行行尾自动补全分号的缘故。例如:

    str:="hello"+
            "world"
    

    或者使用Go标准包也提供的函数strings.Join()来实现这一功能。

    str1:=[]string{"hello","world"}
    str:=strings.Join(str1,",")
    fmt.Println(str)
    

    字符串遍历

    go中有两种方式对字符串进行遍历,一种是utf-8遍历,另一种是Unicode遍历。

        //utf-8遍历
        for i := 0; i < len(s); i++ {
            ch1 := s[i]
            ctype:=reflect.TypeOf(ch1)
            fmt.Printf("%s ",ctype) //uint8
        }
        fmt.Println("=============>Unicode遍历")
        //Unicode遍历
        for _, ch1 := range s {
            ctype:=reflect.TypeOf(ch1)
            fmt.Printf("%s ",ctype) //int32
        }
    

    当然这种遍历都会打印一堆数字
    代码运行后显示ch1的类型为uint8,也就是byte类型,而ch1的类型为int32,也就是rune类型。

    go语言中的源码定义为utf-8文本,不允许其他的表示。但是也存在特殊处理,那就是字符串上使用for…range循环。range循环迭代时,就会解码一个utf-8编码的rune。
    现在既然已经知道上述不管哪种遍历方式,其实质都是字节。所以在打印时,只需要将这些结果转化为字符字面值或者转换其输出类型就可以了。

        //方法一:格式化打印
        for _, ch1 := range s {
            fmt.Printf("%q",ch1) //单引号围绕的字符字面值,由go语法安全的转义
        }
        fmt.Println("==========>方法二")
        //方法二:转化输出格式
        for _, ch2 := range s{
            fmt.Println(string(ch2))
        }
    

    相关文章

      网友评论

          本文标题:【Go基础】字符类型

          本文链接:https://www.haomeiwen.com/subject/hehnmktx.html