Golang fmt.Appendf 函数
最后修改时间 2025 年 5 月 8 日
本教程将解释如何在 Go 中使用 fmt.Appendf
函数。我们将通过实际示例介绍高效的字符串操作,涵盖字符串格式化的基础知识。
fmt.Appendf
函数根据格式说明符进行格式化,并将结果追加到字节切片。在构建字符串时,它比 fmt.Sprintf 更高效。
在 Go 1.19+ 中,fmt.Appendf
提供了一种通过重用已分配内存来构建字符串的高效方法。当追加到具有足够容量的现有切片时,它可以避免分配。
fmt.Appendf 基本示例
fmt.Appendf
最简单的用法是将格式化的文本追加到字节切片。本示例演示了基本的字符串格式化和追加。
package main import ( "fmt" ) func main() { buf := []byte("Existing content: ") name := "Alice" age := 30 buf = fmt.Appendf(buf, "Name: %s, Age: %d", name, age) fmt.Println(string(buf)) }
代码以初始字节切片开始,并追加格式化内容。输出将原始内容和新内容合并到一个字符串中。
多次追加
fmt.Appendf
可以对同一个切片调用多次。本示例展示了通过多次追加进行增量字符串构建。
package main import ( "fmt" ) func main() { buf := []byte{} for i := 1; i <= 5; i++ { buf = fmt.Appendf(buf, "Iteration %d, ", i) } fmt.Println("Result:", string(buf)) }
每个循环迭代都将新的格式化内容追加到切片。最终结果按顺序包含所有追加的字符串。
追加不同数据类型
fmt.Appendf
通过格式动词处理各种数据类型。本示例演示了在一次追加中格式化不同类型。
package main import ( "fmt" "time" ) func main() { buf := []byte("Current status: ") now := time.Now() active := true count := 42 buf = fmt.Appendf(buf, "Active: %t, Count: %d, Time: %v", active, count, now) fmt.Println(string(buf)) }
该示例展示了布尔值、整数和时间值的组合格式化。格式动词(%t、%d、%v)控制每个值的表示方式。
预分配切片容量
预分配切片容量可以提高 fmt.Appendf
的性能。本示例演示了重复追加的容量优化。
package main import ( "fmt" ) func main() { // Preallocate slice with 0 length but 256 capacity buf := make([]byte, 0, 256) for i := 0; i < 10; i++ { buf = fmt.Appendf(buf, "Number %04d\n", i) } fmt.Print(string(buf)) }
预分配的容量可以防止在追加过程中进行多次分配。当最终大小大致已知时,这尤其有益。
追加到现有字符串
fmt.Appendf
通过将字符串转换为字节切片来高效地扩展现有字符串。本示例展示了字符串扩展的实际应用。
package main import ( "fmt" ) func main() { greeting := "Hello" buf := []byte(greeting) name := "Bob" buf = fmt.Appendf(buf, ", %s! How are you?", name) fmt.Println(string(buf)) }
该示例从一个字符串开始,将其转换为字节,然后追加更多内容。这避免了创建中间字符串分配。
使用 Appendf 进行自定义格式化
fmt.Appendf
支持所有标准格式说明符。本示例演示了高级格式化选项。
package main import ( "fmt" "math" ) func main() { buf := []byte("Math results:\n") pi := math.Pi buf = fmt.Appendf(buf, "Pi: %.4f\n", pi) hex := 255 buf = fmt.Appendf(buf, "Hex: %#x\n", hex) sci := 123456789.0 buf = fmt.Appendf(buf, "Scientific: %e\n", sci) fmt.Println(string(buf)) }
该示例展示了浮点精度、十六进制和科学计数法格式化。每次追加都使用不同的格式说明符。
与 Sprintf 的性能比较
本示例将 fmt.Appendf
与 fmt.Sprintf
进行比较,以展示字符串构建中的性能差异。
package main import ( "fmt" "time" ) func buildWithSprintf(n int) string { var s string for i := 0; i < n; i++ { s += fmt.Sprintf("%d ", i) } return s } func buildWithAppendf(n int) string { buf := make([]byte, 0, n*3) // Estimate 3 bytes per number for i := 0; i < n; i++ { buf = fmt.Appendf(buf, "%d ", i) } return string(buf) } func main() { const count = 10000 start := time.Now() buildWithSprintf(count) sprintfTime := time.Since(start) start = time.Now() buildWithAppendf(count) appendfTime := time.Since(start) fmt.Printf("Sprintf: %v\n", sprintfTime) fmt.Printf("Appendf: %v\n", appendfTime) }
fmt.Appendf
对于增量字符串构建来说速度明显更快,尤其是在预分配容量的情况下。它避免了中间分配和复制。
来源
本教程通过实际的字符串格式化和追加示例,介绍了 Go 中的 fmt.Appendf
函数。