ZetCode

Golang append function

last modified May 8, 2025

This tutorial explains how to use the append built-in function in Go. We'll cover slice basics with practical examples of dynamic slice manipulation.

The append function is used to add elements to a slice in Go. It handles automatic resizing of the underlying array when needed. The function returns a new slice containing all original elements plus the new ones.

In Go, append is essential for working with dynamic collections. It efficiently manages memory allocation and copying when slices grow beyond their current capacity.

Basic append example

The simplest use of append adds elements to a slice. This example demonstrates basic slice appending.
Note: Always assign the return value of append to a variable.

basic_append.go
package main

import "fmt"

func main() {
    var nums []int
    
    // Append single elements
    nums = append(nums, 1)
    nums = append(nums, 2)
    nums = append(nums, 3)
    
    fmt.Println(nums) // [1 2 3]
    
    // Append multiple elements
    nums = append(nums, 4, 5, 6)
    fmt.Println(nums) // [1 2 3 4 5 6]
}

The example shows both single and multiple element appending. Each append operation returns a new slice that must be assigned back to the variable.

Appending to a slice with capacity

When a slice has sufficient capacity, append reuses the underlying array. This example demonstrates capacity behavior during append operations.

capacity_append.go
package main

import "fmt"

func main() {
    // Create slice with length 3 and capacity 5
    nums := make([]int, 3, 5)
    nums[0], nums[1], nums[2] = 1, 2, 3
    
    fmt.Printf("Before append: len=%d cap=%d %v\n", 
        len(nums), cap(nums), nums)
    
    // Append within capacity
    nums = append(nums, 4)
    fmt.Printf("After first append: len=%d cap=%d %v\n", 
        len(nums), cap(nums), nums)
    
    // Append beyond capacity
    nums = append(nums, 5, 6)
    fmt.Printf("After second append: len=%d cap=%d %v\n", 
        len(nums), cap(nums), nums)
}

The first append doesn't allocate new memory as capacity is sufficient. The second append triggers a new allocation as it exceeds the capacity.

Appending one slice to another

We can append all elements of one slice to another using the spread operator. This example shows how to combine slices efficiently.

slice_append.go
package main

import "fmt"

func main() {
    fruits := []string{"apple", "banana"}
    moreFruits := []string{"orange", "grape", "kiwi"}
    
    // Append all elements of moreFruits to fruits
    fruits = append(fruits, moreFruits...)
    
    fmt.Println(fruits) // [apple banana orange grape kiwi]
    
    // Create new slice by combining
    allFruits := append([]string{}, fruits...)
    allFruits = append(allFruits, "melon")
    
    fmt.Println(allFruits) // [apple banana orange grape kiwi melon]
}

The ... operator expands the slice into individual elements. This pattern is useful for combining slices without nested slice structures.

Appending to nil slices

Append works with nil slices, automatically creating a new slice when needed. This example demonstrates nil slice behavior with append.

nil_append.go
package main

import "fmt"

func main() {
    var nilSlice []int
    
    fmt.Printf("nilSlice: len=%d cap=%d %v\n", 
        len(nilSlice), cap(nilSlice), nilSlice)
    
    // Append to nil slice
    nilSlice = append(nilSlice, 10)
    fmt.Printf("After append: len=%d cap=%d %v\n", 
        len(nilSlice), cap(nilSlice), nilSlice)
    
    // Multiple appends
    nilSlice = append(nilSlice, 20, 30, 40)
    fmt.Printf("Final state: len=%d cap=%d %v\n", 
        len(nilSlice), cap(nilSlice), nilSlice)
}

The nil slice behaves like an empty slice when used with append. Go handles the initial allocation automatically when first appending to a nil slice.

Appending different types with interfaces

We can append different types to a slice by using the empty interface. This example demonstrates heterogeneous collections with append.

interface_append.go
package main

import "fmt"

func main() {
    var items []interface{}
    
    items = append(items, 42)
    items = append(items, "hello")
    items = append(items, 3.14)
    items = append(items, true)
    
    for i, item := range items {
        fmt.Printf("Item %d: %v (%T)\n", i, item, item)
    }
}

The empty interface interface{} allows storing any type. Each element retains its original type information despite being in the same slice.

Source

Go language specification

This tutorial covered the append function in Go with practical examples of dynamic slice manipulation and growth patterns.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Golang tutorials.