Golang 中的字符类型

GolangGolangBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在上一节中,我们讨论了常用的数值类型。在本节中,我们将学习 Go 语言中的字符类型。

知识点:

  • ASCII 编码
  • UTF-8 编码
  • Unicode 字符集
  • byte
  • rune

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/BasicsGroup(["Basics"]) go(("Golang")) -.-> go/DataTypesandStructuresGroup(["Data Types and Structures"]) go(("Golang")) -.-> go/FunctionsandControlFlowGroup(["Functions and Control Flow"]) go(("Golang")) -.-> go/AdvancedTopicsGroup(["Advanced Topics"]) go/BasicsGroup -.-> go/variables("Variables") go/DataTypesandStructuresGroup -.-> go/strings("Strings") go/FunctionsandControlFlowGroup -.-> go/functions("Functions") go/AdvancedTopicsGroup -.-> go/text_templates("Text Templates") go/AdvancedTopicsGroup -.-> go/base64_encoding("base64 Encoding") subgraph Lab Skills go/variables -.-> lab-149068{{"Golang 中的字符类型"}} go/strings -.-> lab-149068{{"Golang 中的字符类型"}} go/functions -.-> lab-149068{{"Golang 中的字符类型"}} go/text_templates -.-> lab-149068{{"Golang 中的字符类型"}} go/base64_encoding -.-> lab-149068{{"Golang 中的字符类型"}} end

ASCII 编码

在计算机的早期,ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)编码格式被广泛使用。它使用 7 位(bit)来表示字符,可以表示 128(2^7)个字符。其中,0 到 31 位以及 127 位表示无法显示的控制字符,而 32 到 126 位则表示日常使用的大写和小写字母、数字以及标点符号。详见表格

随着计算机的发展,支持不同语言的需求逐渐增加。ASCII 编码无法满足这一需求。因此,不同语言开发了自己的编码格式,例如简体中文的 GB2312、韩语的 EUC-KR 以及俄语的 KOI8-R。

然而,由于世界上存在许多语言体系,需要一种能够统一所有语言的编码格式。Unicode 应运而生,满足了这一需求。

Unicode 字符集

1991 年,Unicode 联盟发布了 Unicode 字符集的第一个版本。其目标是将所有语言统一为一种编码格式,使全球的计算机能够更轻松地显示和处理文本,并避免在多语言环境中的兼容性问题。

然而,Unicode 只是一个字符集;它定义了字符的编码,但并未规定这些编码的存储方式。这导致 Unicode 在很长一段时间内难以广泛采用,直到互联网的兴起。

UTF-8 编码

随着互联网的不断发展,UTF-8 作为一种 Unicode 实现编码逐渐流行起来。它是一种可变长度编码,这意味着不同的符号在 UTF-8 中可以有不同的字节长度。

例如,对于英文字母(属于 ASCII 范围),它们用 1 个字节表示。字符 'y'(Unicode 值为 121)占用 1 个字节。

在日常使用中,大多数中文字符占用 3 个字节。例如,字符 '实'(Unicode 值为 23454)占用 3 个字节。

然而,也有一些中文字符占用 4 个字节。这是因为中文字符数量超过 10 万个,而根据下图所示,3 个字节只能表示略多于 6 万个字符,因此少数中文字符需要 4 个字节来表示。

UTF-8 编码的另一个优势是它向后兼容 ASCII 编码。实际上,ASCII 是 UTF-8 的子集。UTF-8 中的前 128 个字符与 ASCII 字符一一对应。这意味着原本使用 ASCII 的软件可以继续使用,几乎不需要修改。由于这些优势,UTF-8 逐渐成为首选的编码格式。

Go 编程语言的创造者 Rob Pike 和 Ken Thompson 也是 UTF-8 的发明者,因此 Go 对 UTF-8 有着特殊的亲和力。Go 要求源代码文件以 UTF-8 编码保存。在操作文本字符时,UTF-8 编码是首选。此外,标准库还提供了许多与 UTF-8 编码和解码相关的函数。

byte 和 rune

byteuint8 的别名,占用一个字节(8 位)。它可以用来表示 ASCII 表中的所有字符。然而,由于 byte 能表示的值范围有限(256 或 2^8),在处理复合字符(如中文字符)时,我们需要使用 rune 类型。

创建一个名为 byte.go 的新文件,并输入以下代码:

cd ~/project
touch byte.go
package main

import "fmt"

func main() {
    var a byte = 76
    fmt.Printf("Value of a: %c\n", a)

    var b uint8 = 76
    fmt.Printf("Value of b: %c\n", b)

    var c byte = 'L'
    fmt.Printf("Value of c: %c\n", c)
}

运行程序后,将输出以下结果:

go run byte.go
Value of a: L
Value of b: L
Value of c: L

%c 占位符用于输出字符。可以看出,当值相同时,byte 类型和 uint8 类型会产生相同的输出。通过参考 ASCII 表,可以看到字母 'A' 的 ASCII 值为 65。当我们使用整数占位符 %d 输出该值时,结果也是 65。

因此,显而易见,Go 中的 byte 等同于整数类型中的 uint8rune 也是如此,但它表示不同的整数值范围。

runeint32 的别名,占用四个字节(32 位)。它用于表示复合字符,例如表情符号。

更新 byte.go 文件,添加以下代码:

package main

import "fmt"

func main() {
    var a rune = '😊' // 微笑表情
    fmt.Printf("Value of a: %c\n", a)

    var b int32 = 9829 // Unicode 字符的十进制表示(心形符号)
    fmt.Printf("Value of b: %c\n", b)
    var c rune = 0x1F496 // Unicode 字符的十六进制表示(闪烁的心形表情)
    fmt.Printf("Value of c: %c\n", c)

    var d rune = '\u0041' // 使用码点表示的 Unicode 字符(大写字母 'A')
    fmt.Printf("Value of d: %c\n", d)
    var e rune = '\U0001F609' // 使用码点表示的 Unicode 字符(眨眼表情)
    fmt.Printf("Value of e: %c\n", e)
}

运行程序后,将显示以下输出:

go run byte.go

注意: 请在 Desktop 或 WebIDE 终端中运行程序,但避免在 LabEx VM 顶部的 Terminal Tab 中运行。

Value of a: 😊
Value of b: ♥
Value of c: 💖
Value of d: A
Value of e: 😉
  • 变量 a 表示微笑表情 '😊'。
  • 变量 b 使用 Unicode 字符的十进制表示(9829)初始化,对应心形符号 '♥'。
  • 变量 c 使用 Unicode 字符的十六进制表示(0x1F496)初始化,对应闪烁的心形表情 '💖'。
  • 变量 d 使用 Unicode 格式 \u0041 表示大写字母 'A'。
  • 变量 e 使用 \U 格式和码点 0001F609 表示眨眼表情 '😉'。

注意: 在 Go 中,单引号和双引号是不同的。单引号用于表示字符,而双引号用于声明字符串。因此,在声明 byterune 类型时,应使用单引号,否则会报错。

测验

现在,让我们巩固一下所学内容。创建一个名为 rune.go 的新文件,并输入以下代码。完成代码,使得十六进制数 0x1F648 被赋值给变量 a,并且程序能够正确输出其值。

  • 要求: 文件 rune.go 应放置在 ~/project 目录中。
  • 提示: 对于较长的十六进制数,必须使用指定的格式。
package main

import "fmt"

func main() {
    var a rune = 0x1F648
    fmt.Printf("The value of a is: %c\n", a)
}
✨ 查看解决方案并练习

总结

让我们回顾一下本节所学内容:

  • ASCII 字符占用一个字节,可以表示 128 个字符。
  • UTF-8 编码是 Unicode 字符集的一种形式。它是一种可变长度编码,其字节长度取决于所表示的字符。
  • byte 数据类型可用于表示 ASCII 字符,而 rune 数据类型可用于表示 Unicode 字符。
  • byte 数据类型可以表示 ASCII 字符,rune 数据类型可以表示 Unicode 字符。

在本节中,我们首先解释了 ASCII、UTF-8 和 Unicode。然后,我们解释了字符数据类型 byterune 与整数数据类型之间的关系。