← Back to Go Course | Chapter 5: Arrays Slices Maps | Lesson 3 of 7

Creating Slices with make and append

make() builds you an empty container with room to grow, and append() is how you add more items to a slice, handing you back the (maybe resized) result.
Syntax
go
name := make([]type, length, capacity)
name = append(name, value1, value2)
name = append(name, other...)

Creating a Slice with make

make([]Type, length) creates a slice of the given length, filled with zero values, ready to index into directly. An optional third argument sets the initial capacity separately from the length.

Example: Creating a Slice with make

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// main is where the program starts running
func main() {
	// Short declaration: create s and infer the type
	s := make([]int, 3)
	s[0], s[1], s[2] = 1, 2, 3
	// Print the values followed by a newline
	fmt.Println(s)
}

Appending Elements

append adds one or more elements to the end of a slice and returns the resulting slice, which you must assign back to a variable, because append may or may not return the same underlying array depending on whether it had room to grow.

Note: Always write 's = append(s, ...)' -- forgetting to reassign is one of the most common Go beginner bugs.

Example: Appending Elements

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// main is where the program starts running
func main() {
	// Short declaration: create nums and infer the type
	nums := []int{1, 2}
	// append adds elements and returns the updated slice
	nums = append(nums, 3, 4, 5)
	// Print the values followed by a newline
	fmt.Println(nums)
}

Growing Beyond Capacity

When append needs more room than the current capacity allows, Go allocates a new, larger underlying array, copies the existing elements over, and returns a slice pointing at the new array -- which is why the old and new slice can end up independent after a big enough append.

Example: Growing Beyond Capacity

markup
// Every Go file belongs to a package; main builds an executable
package main

// Import the fmt package
import "fmt"

// main is where the program starts running
func main() {
	// Short declaration: create s and infer the type
	s := make([]int, 0, 2)
	// Loop: repeat while the condition holds
	for i := 1; i <= 5; i++ {
		// append adds elements and returns the updated slice
		s = append(s, i)
		// Print the values followed by a newline
		fmt.Println("len:", len(s), "cap:", cap(s))
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Ignoring append's return value, assuming it modifies the original slice variable in place -- you must reassign the result.
  2. Calling make([]int, 5) expecting an empty slice, when it actually creates a slice of length 5 filled with zero values.
  3. Appending to a slice obtained by slicing another slice and being surprised when it overwrites data in the original's underlying array.
Chapter Summary
  • make([]Type, length, capacity) allocates a new slice with a given size.
  • append(slice, values...) adds elements, returning a (possibly new) slice that must be reassigned.
  • If a slice's capacity is exceeded, append allocates a new, larger underlying array automatically.
  • make(slice, 0, n) pre-allocates capacity while keeping length 0, useful when the final size is roughly known.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.