Golang fmt.Append function
last modified May 8, 2025
This tutorial explains how to use the fmt.Append function in Go.
We'll cover string building basics with practical examples of efficient string
manipulation.
The fmt.Append function is used to efficiently build strings by appending formatted data to byte slices. It provides a performance advantage over string concatenation for complex string building operations.
In Go, fmt.Append is part of the fmt package and was introduced
in Go 1.19. It works similarly to fmt.Printf but writes to a
byte slice instead of an io.Writer.
Basic fmt.Append example
The simplest use of fmt.Append appends formatted strings to a
byte slice. This example demonstrates basic string appending.
Note: The function returns a new slice, it doesn't modify
the original.
package main
import (
"fmt"
)
func main() {
buf := []byte("Hello, ")
buf = fmt.Append(buf, "World!")
fmt.Println(string(buf)) // Convert back to string for printing
// Append multiple values
nums := []byte("Numbers: ")
nums = fmt.Append(nums, 1, 2, 3)
fmt.Println(string(nums))
}
The function appends formatted values to the byte slice. The original slice may be empty or contain existing data.
Appending with formatting verbs
fmt.Append supports the same formatting verbs as fmt.Printf.
This example shows formatted number appending.
package main
import (
"fmt"
)
func main() {
buf := []byte("Formatted values: ")
// Append with different format verbs
buf = fmt.Appendf(buf, "Int: %d, Float: %.2f, Bool: %t", 42, 3.14159, true)
fmt.Println(string(buf))
// Hexadecimal example
hexBuf := []byte("Hex: ")
hexBuf = fmt.Appendf(hexBuf, "%x", 255)
fmt.Println(string(hexBuf))
}
The Appendf variant allows precise control over formatting.
Format verbs work exactly like in other fmt package functions.
Appending slices and arrays
fmt.Append can append entire slices and arrays. This example
shows how to efficiently build strings from collections.
package main
import (
"fmt"
)
func main() {
names := []string{"Alice", "Bob", "Charlie"}
buf := []byte("Names: ")
// Append each name with separator
for _, name := range names {
buf = fmt.Append(buf, name, ", ")
}
// Remove trailing comma and space
if len(names) > 0 {
buf = buf[:len(buf)-2]
}
fmt.Println(string(buf))
// Alternative with fmt.Appendln
buf = []byte("Names:\n")
for _, name := range names {
buf = fmt.Appendln(buf, name)
}
fmt.Println(string(buf))
}
The example shows two approaches: comma-separated values and line-separated. The function handles each element's string conversion automatically.
Performance comparison with strings.Builder
fmt.Append can be more efficient than strings.Builder for some
use cases. This example compares the performance characteristics.
package main
import (
"fmt"
"strings"
"time"
)
func buildWithBuilder(count int) string {
var b strings.Builder
for i := 0; i < count; i++ {
fmt.Fprintf(&b, "Item %d, ", i)
}
return b.String()
}
func buildWithAppend(count int) string {
buf := []byte{}
for i := 0; i < count; i++ {
buf = fmt.Append(buf, "Item ", i, ", ")
}
return string(buf)
}
func main() {
const count = 10000
start := time.Now()
buildWithBuilder(count)
builderTime := time.Since(start)
start = time.Now()
buildWithAppend(count)
appendTime := time.Since(start)
fmt.Printf("strings.Builder: %v\n", builderTime)
fmt.Printf("fmt.Append: %v\n", appendTime)
}
The performance difference depends on the use case. fmt.Append
often wins for many small appends, while strings.Builder may be better for
fewer, larger writes.
Appending custom types
fmt.Append works with any type that implements the Stringer
interface. This example demonstrates custom type appending.
package main
import (
"fmt"
)
type Point struct {
X, Y int
}
func (p Point) String() string {
return fmt.Sprintf("(%d,%d)", p.X, p.Y)
}
func main() {
buf := []byte("Points: ")
p1 := Point{10, 20}
p2 := Point{30, 40}
buf = fmt.Append(buf, p1, " ", p2)
fmt.Println(string(buf))
// Works with pointers too
buf = []byte("Pointer points: ")
buf = fmt.Append(buf, &p1, " ", &p2)
fmt.Println(string(buf))
}
The String method is automatically called when appending custom types. This provides flexible formatting for user-defined data structures.
Error handling with fmt.Append
fmt.Append doesn't return errors, making it simpler than some
other formatting functions. This example shows error-free usage patterns.
package main
import (
"fmt"
)
func main() {
// No error handling needed
buf := []byte{}
buf = fmt.Append(buf, "This", " ", "works", " ", 123)
fmt.Println(string(buf))
// Even with invalid format strings, it won't panic
buf = []byte{}
buf = fmt.Appendf(buf, "Value: %d", "not a number") // %d expects number
fmt.Println(string(buf)) // Still produces output (with wrong format)
// For critical formatting, validate first
value := "not a number"
if _, err := fmt.Sscanf(value, "%d", new(int)); err == nil {
buf = fmt.Appendf(buf, "Valid number: %d", value)
} else {
buf = fmt.Append(buf, "Invalid number: ", value)
}
fmt.Println(string(buf))
}
While fmt.Append won't panic on format mismatches, the output
may not be as expected. For critical formatting, validate inputs first.
Building complex strings
fmt.Append excels at building complex strings incrementally.
This example shows a multi-step string construction.
package main
import (
"fmt"
"time"
)
func buildReport() []byte {
buf := []byte("REPORT\n")
buf = fmt.Appendf(buf, "Generated: %s\n\n", time.Now().Format(time.RFC1123))
// Add header
buf = fmt.Append(buf, "ITEM".padRight(20), "QUANTITY".padRight(10), "PRICE\n")
buf = fmt.Append(buf, "----".padRight(20), "--------".padRight(10), "-----\n")
// Add items
items := []struct {
name string
quantity int
price float64
}{
{"Widget", 5, 12.99},
{"Gadget", 2, 29.95},
{"Thingy", 10, 1.49},
}
for _, item := range items {
buf = fmt.Appendf(buf, "%-20s%-10d$%.2f\n",
item.name, item.quantity, item.price)
}
// Add footer
buf = fmt.Append(buf, "\nTotal items: ", len(items), "\n")
return buf
}
func main() {
report := buildReport()
fmt.Println(string(report))
}
// Helper function for padding
func (s string) padRight(width int) string {
if len(s) >= width {
return s
}
return s + strings.Repeat(" ", width-len(s))
}
The example demonstrates building a formatted report with headers, data rows,
and footer. fmt.Append efficiently handles each part.
Source
This tutorial covered the fmt.Append function in Go with practical
examples of efficient string building and formatting.
Author
List all Golang tutorials.