【Go基础】字符类型

abboo · · 130 次点击 · · 开始浏览    

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))
    }

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:abboo

查看原文:【Go基础】字符类型

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:1006366459

130 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传