ZetCode

Go Rune

最后修改时间 2024 年 4 月 11 日

在本文中,我们将展示如何在 Golang 中使用 rune。

Rune 是 int32 数据类型的一个别名。它表示一个 Unicode 码点。Unicode 码点或码位是一个数值,通常用于表示 Unicode 字符。int32 的大小足以表示当前 140,000 个 Unicode 字符的容量。

ASCII 定义了 128 个字符,由码点 0-127 标识。Unicode 是 ASCII 的超集,它定义了 1,114,112 个码点的编码空间。

最初的 rune 这个词属于各种古代日耳曼民族的书面语言,特别是斯堪的纳维亚人和盎格鲁-撒克逊人。

字符串是字节序列;更确切地说,是任意字节的切片。在 Go 中,源代码是 UTF8。字符串可以包含以 UTF-8 编码的 Unicode 文本,它使用一到四个字节来编码所有 Unicode 码点。

Go Rune 常量

Go rune 常量由一对单引号 ' 分隔。

rune_constant.go
package main

import (
    "fmt"
    "reflect"
)

func main() {

    a1 := '🦍'
    var a2 = 'k'
    var a3 rune = '🦡'

    fmt.Printf("%c - %s\n", a1, reflect.TypeOf(a1))
    fmt.Printf("%c - %s\n", a2, reflect.TypeOf(a2))
    fmt.Printf("%c - %s\n", a3, reflect.TypeOf(a3))
}

我们定义了三个 rune 常量。

a1 := '🦍'
var a2 = 'k'
var a3 rune = '🦡'

我们有两个 emoji 和一个 ASCII 字符。如果未显式指定,Go 会自动推断 rune 类型。

fmt.Printf("%c - %s\n", a1, reflect.TypeOf(a1))
fmt.Printf("%c - %s\n", a2, reflect.TypeOf(a2))
fmt.Printf("%c - %s\n", a3, reflect.TypeOf(a3))

我们打印字符及其类型。

$ go run rune_constant.go
🦍 - int32
k - int32
🦡 - int32

我们可以使用转义字符来定义 rune 常量。

rune_escapes.go
package main

import (
    "fmt"
)

func main() {

    a1 := '🧺'
    a2 := '\u2665'
    a3 := '\U0001F3A8'

    fmt.Printf("%c\n", a1)
    fmt.Printf("%c\n", a2)
    fmt.Printf("%c\n", a3)
}

我们定义了三个常量;其中两个使用了转义字符。

a2 := '\u2665'

在第一种情况下,\u 后面跟着正好四个十六进制数字。

a3 := '\U0001F3A8'

在第二种情况下,\U 后面跟着正好八个十六进制数字。

$ go run rune_escapes.go
🧺
♥
🎨

Go Rune Unicode 码点

Unicode 码点指的是 Unicode 表中的字符。

code_points.go
package main

import "fmt"

func main() {

    s1 := "falcon"
    r1 := []rune(s1)
    fmt.Printf("%U\n", r1)

    s2 := "🐧🐧🐧"
    r2 := []rune(s2)
    fmt.Printf("%U\n", r2)
}

使用 %U 格式动词,我们可以得到 Unicode 码点。

$ go run code_points.go 
[U+0066 U+0061 U+006C U+0063 U+006F U+006E]
[U+1F427 U+1F427 U+1F427]

Go 计算 Rune 数量

在下面的示例中,我们计算字符串中 rune 的数量。

count.go
package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {

    msg := "one 🐜"
    n1 := len(msg)
    n2 := utf8.RuneCountInString(msg)

    fmt.Println(n1)
    fmt.Println(n2)
}

使用 len 函数,我们可以得到字节数。要计算 rune 的数量,我们使用 utf8.RuneCountInString 函数。

$ go run count.go
8
5

Go Rune 和字节

Go 中的字节是 uint8 的别名;它是一个“ASCII 字节”。

runes_bytes.go
package main

import (
    "fmt"
)

func main() {

    msg := "🐘 🦥 🐋"

    data := []rune(msg)
    fmt.Println(data)

    data2 := []byte(msg)
    fmt.Println(data2)
}

我们有一个由三个 emoji 和两个空格组成的字符串。我们打印 rune 和字节的切片进行比较。

$ go run rune_bytes.go
[128024 32 129445 32 128011]
[240 159 144 152 32 240 159 166 165 32 240 159 144 139]

Go 遍历 Rune

for/range 形式会遍历 rune。

loop.go
package main

import (
    "fmt"
)

func main() {

    msg := "one 🐘 and three 🐋"

    for idx, e := range msg {
        fmt.Printf("Char:%s Byte pos: %d \n", string(e), idx)
    }
}

该示例遍历 rune。它显示了字符及其在字符串中的字节位置。

$ go run loop.go
Char:o Byte pos: 0
Char:n Byte pos: 1
Char:e Byte pos: 2
Char:  Byte pos: 3
Char:🐘 Byte pos: 4
Char:  Byte pos: 8
Char:a Byte pos: 9
Char:n Byte pos: 10
Char:d Byte pos: 11
Char:  Byte pos: 12
Char:t Byte pos: 13
Char:h Byte pos: 14
Char:r Byte pos: 15
Char:e Byte pos: 16
Char:e Byte pos: 17
Char:  Byte pos: 18
Char:🐋 Byte pos: 19

在下一个示例中,我们有另一种遍历 rune 的方法。

loop2.go
package main

import (
    "fmt"
)

func main() {

    msg := "one 🐘 and three 🐋"
    data := []rune(msg)

    for i := 0; i < len(data); i++ {
        fmt.Printf("Char %c Unicode: %U, Rune pos: %d\n", data[i], data[i], i)
    }

    fmt.Println()
}

我们将字符串转换为 rune 切片,然后使用 for 循环遍历该切片。

$ go run loop2.go 
Char o Unicode: U+006F, Rune pos: 0
Char n Unicode: U+006E, Rune pos: 1
Char e Unicode: U+0065, Rune pos: 2
Char   Unicode: U+0020, Rune pos: 3
Char 🐘 Unicode: U+1F418, Rune pos: 4
Char   Unicode: U+0020, Rune pos: 5
Char a Unicode: U+0061, Rune pos: 6
Char n Unicode: U+006E, Rune pos: 7
Char d Unicode: U+0064, Rune pos: 8
Char   Unicode: U+0020, Rune pos: 9
Char t Unicode: U+0074, Rune pos: 10
Char h Unicode: U+0068, Rune pos: 11
Char r Unicode: U+0072, Rune pos: 12
Char e Unicode: U+0065, Rune pos: 13
Char e Unicode: U+0065, Rune pos: 14
Char   Unicode: U+0020, Rune pos: 15
Char 🐋 Unicode: U+1F40B, Rune pos: 16

来源

Go 中的字符串、字节、Rune 和字符

在本文中,我们使用了 Go rune。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出所有 Go 教程