ZetCode

Golang strconv.AppendQuote

最后修改于 2025 年 4 月 20 日

本教程讲解如何在 Go 中使用 strconv.AppendQuote 函数。我们将通过实际示例讲解字符串引用的基础知识,并演示如何追加带引用的字符串。

strconv.AppendQuote 函数将一个双引号引起来的 Go 字符串字面量追加到一个字节切片。它会根据 Go 的语法规则正确地转义特殊字符。

此函数对于构建需要包含带引用字符串的字节切片非常有用。它比先创建字符串然后转换为字节更有效率。

基本的 strconv.AppendQuote 示例

strconv.AppendQuote 最简单的用法是将一个带引用的字符串追加到字节切片。这里我们演示了对不同字符串输入的基本用法。

basic_appendquote.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    buf := []byte("Prefix: ")
    buf = strconv.AppendQuote(buf, "Hello, World!")
    
    fmt.Println(string(buf))
    
    buf = []byte{}
    buf = strconv.AppendQuote(buf, "Go\"lang")
    fmt.Println(string(buf))
}

我们从一个包含“Prefix: ”的字节切片开始,然后追加一个带引用的字符串。第二个示例展示了如何引用一个包含双引号字符的字符串。

追加多个带引用的字符串

strconv.AppendQuote 可以多次使用来构建复杂的字节切片。此示例演示了如何构建一个类似 JSON 的结构。

multiple_append.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    buf := []byte("{")
    buf = append(buf, '\n')
    
    buf = append(buf, "  name: "...)
    buf = strconv.AppendQuote(buf, "John Doe")
    buf = append(buf, ',', '\n')
    
    buf = append(buf, "  email: "...)
    buf = strconv.AppendQuote(buf, "john@example.com")
    buf = append(buf, '\n', '}')
    
    fmt.Println(string(buf))
}

我们通过交替使用 AppendQuote 和常规追加操作来构建结构化的字节切片。结果是一个格式正确的带引用的输出。

处理特殊字符

strconv.AppendQuote 会自动转义特殊字符。此示例展示了它如何处理输入字符串中的各种特殊情况。

special_chars.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    tests := []string{
        "Line\nBreak",
        "Tab\tHere",
        "Back\\Slash",
        "Quote\"Mark",
        "Non-ASCII: 日本語",
    }
    
    for _, s := range tests {
        buf := strconv.AppendQuote([]byte{}, s)
        fmt.Printf("%-20s → %s\n", s, string(buf))
    }
}

该函数会正确转义换行符、制表符、反斜杠和引号。它还会正确处理非 ASCII 字符,将它们按原样包含在输出中。

性能比较

此示例比较了 AppendQuote 与创建带引用字符串的替代方法的性能。

performance.go
package main

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

func main() {
    const iterations = 1000000
    testStr := "The quick brown fox jumps over the lazy dog"
    
    // Benchmark AppendQuote
    start := time.Now()
    buf := make([]byte, 0, 100)
    for i := 0; i < iterations; i++ {
        buf = strconv.AppendQuote(buf[:0], testStr)
    }
    fmt.Println("AppendQuote duration:", time.Since(start))
    
    // Benchmark Quote + conversion
    start = time.Now()
    for i := 0; i < iterations; i++ {
        _ = []byte(strconv.Quote(testStr))
    }
    fmt.Println("Quote+conversion duration:", time.Since(start))
    
    // Benchmark fmt.Sprintf
    start = time.Now()
    for i := 0; i < iterations; i++ {
        _ = []byte(fmt.Sprintf("%q", testStr))
    }
    fmt.Println("fmt.Sprintf duration:", time.Since(start))
}

在直接构建字节切片时,AppendQuote 比替代方法快得多。它避免了中间的字符串分配和转换。

构建 CSV 数据

这个实际示例展示了如何使用 AppendQuote 来构建 CSV 数据,并正确引用包含特殊字符的字段。

csv_builder.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    records := [][]string{
        {"Name", "Email", "Phone"},
        {"John Doe", "john@example.com", "123-456-7890"},
        {"Jane \"The Boss\" Smith", "jane@example.com", "987-654-3210"},
        {"Bob, Jr.", "bob@example.com", "555-123-4567"},
    }
    
    var csvData []byte
    for _, record := range records {
        for i, field := range record {
            if i > 0 {
                csvData = append(csvData, ',')
            }
            csvData = strconv.AppendQuote(csvData, field)
        }
        csvData = append(csvData, '\n')
    }
    
    fmt.Println(string(csvData))
}

我们通过正确引用每个字段来构建 CSV 文件。包含逗号或引号的字段会自动转义,从而生成有效的 CSV 输出。

自定义 JSON 编码

此示例演示了一个简化的 JSON 编码器,它在 JSON 输出中使用 AppendQuote 来处理字符串值。

json_encoder.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    data := map[string]string{
        "name":    "Alice",
        "address": "123 \"Main\" St",
        "city":    "New York",
    }
    
    var jsonBuf []byte
    jsonBuf = append(jsonBuf, '{', '\n')
    
    first := true
    for k, v := range data {
        if !first {
            jsonBuf = append(jsonBuf, ',', '\n')
        }
        first = false
        
        jsonBuf = strconv.AppendQuote(jsonBuf, k)
        jsonBuf = append(jsonBuf, ':', ' ')
        jsonBuf = strconv.AppendQuote(jsonBuf, v)
    }
    
    jsonBuf = append(jsonBuf, '\n', '}')
    fmt.Println(string(jsonBuf))
}

我们通过引用键和值来构建 JSON 对象。输入字符串中的特殊字符会在 JSON 输出中被正确转义。

追加到现有缓冲区

此示例展示了在性能敏感的代码中重复调用 AppendQuote 时如何有效地重用缓冲区。

buffer_reuse.go
package main

import (
    "fmt"
    "strconv"
)

func main() {
    messages := []string{
        "First message",
        "Second message with \"quotes\"",
        "Third message\nwith newline",
    }
    
    // Pre-allocate buffer with capacity
    buf := make([]byte, 0, 256)
    
    for _, msg := range messages {
        // Reset buffer length while keeping capacity
        buf = buf[:0]
        
        buf = append(buf, "-> "...)
        buf = strconv.AppendQuote(buf, msg)
        buf = append(buf, '\n')
        
        fmt.Print(string(buf))
    }
}

我们在每次迭代中重用相同的缓冲区,重置其长度但保留分配的容量。这减少了紧密循环中的内存分配。

来源

Go strconv 包文档

本教程通过构建包含带引用字符串的字节切片的实际示例,介绍了 Go 中的 strconv.AppendQuote 函数。

作者

我叫 Jan Bodnar,是一名充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直撰写编程文章。至今,我已撰写了超过 1400 篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Go 教程