ZetCode

Golang strconv.AppendQuoteRune

最后修改于 2025 年 4 月 20 日

本教程将介绍如何在 Go 中使用 `strconv.AppendQuoteRune` 函数。我们将通过实际示例涵盖 rune 引用的基础知识。

`strconv.AppendQuoteRune` 函数将单个引用的 rune 表示形式附加到字节切片。它对于高效的字符串构建非常有用。

该函数会处理特殊字符的转义,并返回扩展后的字节切片。与字符串拼接相比,它在构建带引号的输出时效率更高。

基本的 strconv.AppendQuoteRune 示例

`strconv.AppendQuoteRune` 最简单的用法是将一个带引号的 rune 附加到字节切片。这里我们展示了基本用法。

basic_append.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    buf := []byte("Rune: ")
    buf = strconv.AppendQuoteRune(buf, 'A')
    
    fmt.Println(string(buf))
}

我们从一个包含 "Rune: " 的字节切片开始。我们向其中附加一个带引号的 'A' rune。输出显示了转换回字符串的组合结果。

附加特殊字符

`strconv.AppendQuoteRune` 会自动转义特殊字符。此示例展示了它如何处理各种 rune。

special_chars.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    buf := []byte("Quoted: ")
    
    runes := []rune{'\n', '\t', '\'', '\\', '字'}
    
    for _, r := range runes {
        buf = strconv.AppendQuoteRune(buf, r)
        buf = append(buf, ' ')
    }
    
    fmt.Println(string(buf))
}

我们将几个特殊 rune 附加到一个缓冲区中。该函数会正确转义换行符、制表符、引号和反斜杠。非 ASCII rune 也会被处理。

构建带引号的 Rune 列表

此示例演示了如何在循环中使用 `AppendQuoteRune` 高效地构建带引号的 rune 列表。

rune_list.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    buf := []byte("Runes: [")
    runes := []rune{'a', 'b', 'c', '☺', '世'}
    
    for i, r := range runes {
        if i > 0 {
            buf = append(buf, ',', ' ')
        }
        buf = strconv.AppendQuoteRune(buf, r)
    }
    
    buf = append(buf, ']')
    fmt.Println(string(buf))
}

我们构建了一个逗号分隔的带引号 rune 列表。该函数高效地将每个带引号的 rune 附加到缓冲区,而无需创建中间字符串。

与 QuoteRune 比较

此示例将 `AppendQuoteRune` 与 `QuoteRune` 进行比较,以展示 append 版本的性能优势。

compare_quote.go
package main

import (
    "fmt"
    "strconv"
    "strings"
)

func main() {
    // Using QuoteRune (less efficient)
    var builder strings.Builder
    builder.WriteString("Using QuoteRune: ")
    builder.WriteString(strconv.QuoteRune('X'))
    fmt.Println(builder.String())
    
    // Using AppendQuoteRune (more efficient)
    buf := []byte("Using AppendQuoteRune: ")
    buf = strconv.AppendQuoteRune(buf, 'X')
    fmt.Println(string(buf))
}

在增量构建输出时,`AppendQuoteRune` 更高效。它避免了像 `QuoteRune` 那样创建中间字符串对象。

附加到现有 JSON

这个实际示例展示了在构建带有带引号 rune 值的 JSON 输出时使用 `AppendQuoteRune`。

json_example.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    buf := []byte(`{"symbols": [`)

    symbols := []rune{'€', '$', '¥', '£'}
    
    for i, s := range symbols {
        if i > 0 {
            buf = append(buf, ',', ' ')
        }
        buf = strconv.AppendQuoteRune(buf, s)
    }
    
    buf = append(buf, ']', '}')
    fmt.Println(string(buf))
}

我们构造了一个带引号货币符号的 JSON 数组。该函数确保每个 rune 在 JSON 输出中都被正确引用和转义。

处理无效的 UTF-8

此示例演示了 `AppendQuoteRune` 如何通过正确转义来处理无效的 UTF-8 rune。

invalid_utf8.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    buf := []byte("Invalid: ")
    
    // Invalid UTF-8 sequence
    invalidRune := rune(0xDC00) // Lone surrogate
    
    buf = strconv.AppendQuoteRune(buf, invalidRune)
    fmt.Println(string(buf))
}

该函数使用 Go 的转义序列格式正确转义无效的 UTF-8 rune。这确保了即使输入错误,输出仍然是有效的 UTF-8。

性能基准测试

此示例将 `AppendQuoteRune` 与字符串拼接进行基准测试,以展示其性能优势。

benchmark.go
package main

import (
    "fmt"
    "strconv"
    "strings"
    "time"
)

func main() {
    const iterations = 100000
    testRune := '世'
    
    // Benchmark AppendQuoteRune
    start := time.Now()
    buf := make([]byte, 0, iterations*6)
    for i := 0; i < iterations; i++ {
        buf = strconv.AppendQuoteRune(buf, testRune)
    }
    _ = string(buf)
    fmt.Println("AppendQuoteRune:", time.Since(start))
    
    // Benchmark string concatenation
    start = time.Now()
    var s strings.Builder
    for i := 0; i < iterations; i++ {
        s.WriteString(strconv.QuoteRune(testRune))
    }
    _ = s.String()
    fmt.Println("String concat:", time.Since(start))
}

对于构建大型带引号的输出,`AppendQuoteRune` 速度明显更快。它通过直接操作字节切片来避免内存分配。

来源

Go strconv 包文档

本教程通过实际示例,在各种场景下高效地对 rune 进行引用,介绍了 Go 中的 `strconv.AppendQuoteRune` 函数。

作者

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

列出所有 Go 教程