Question
I want to combine the slice []int{1, 2} with the slice []int{3, 4} in Go.
I tried this:
append([]int{1, 2}, []int{3, 4})
but I got this error:
cannot use []int literal (type []int) as type int in append
The documentation seems to suggest this should be possible. What am I missing?
I also saw this form in the documentation:
slice = append(slice, anotherSlice...)
Why does that version work?
Short Answer
By the end of this page, you will understand how Go's append function works, why appending one slice to another requires the ... operator, and how to safely combine slices in real programs.
Concept
In Go, a slice is a dynamic view over an underlying array. The built-in append function is used to add elements to a slice.
The important detail is this:
append(slice, elements...)
append expects individual elements of the slice's element type after the first argument.
For example, if you have a []int, then append expects one or more int values:
nums := []int{1, 2}
nums = append(nums, 3, 4)
That works because 3 and 4 are int values.
But this does not work:
append([]int{1, 2}, []int{3, 4})
because the second argument is a whole slice, not individual values.
Mental Model
Think of append like adding items to a shopping basket.
append(basket, apple, banana)means: add these individual items.append(basket, anotherBasket)means: try to add a whole basket as if it were a single item.append(basket, anotherBasket...)means: open the second basket and pour all its items into the first one.
The ... operator is the “unpack everything inside” instruction.
Syntax and Examples
Core syntax
result := append(slice, element1, element2)
result := append(slice, anotherSlice...)
Example: append individual values
package main
import "fmt"
func main() {
nums := []int{1, 2}
nums = append(nums, 3, 4)
fmt.Println(nums)
}
Output:
[1 2 3 4]
Here, 3 and 4 are individual int values.
Example: concatenate two slices
package main
import "fmt"
func main() {
a := []{, }
b := []{, }
result := (a, b...)
fmt.Println(result)
}
Step by Step Execution
Consider this code:
package main
import "fmt"
func main() {
a := []int{1, 2}
b := []int{3, 4}
result := append(a, b...)
fmt.Println(result)
}
Step-by-step
a := []int{1, 2}creates a slice with two integers.b := []int{3, 4}creates another slice with two integers.append(a, b...)starts withaas the destination slice.b...expands into the values3, 4.- Go treats the call like this conceptually:
append(a, 3, 4)
- The new elements are added to the end of
a. - The returned slice is assigned to
result.
Real World Use Cases
Slices are used everywhere in Go, so concatenation comes up often.
Common use cases
- Combining API results: merge data from multiple pages of an API response.
- Building filtered lists: append matched items into a result slice.
- Collecting logs or events: combine batches before processing.
- Reading files or network chunks: join pieces of data into one slice.
- Middleware and routing: combine lists of handlers or configuration values.
Example: merging paginated results
allUsers := []string{"alice", "bob"}
nextPageUsers := []string{"carol", "dave"}
allUsers = append(allUsers, nextPageUsers...)
Example: collecting valid values
numbers := []int{1, 2}
moreNumbers := []int{3, 4, 5}
numbers = append(numbers, moreNumbers...)
This pattern is simple but very common in production code.
Real Codebase Usage
In real Go projects, developers use append in a few common ways.
1. Building result slices
var result []int
for _, n := range []int{1, 2, 3, 4} {
if n%2 == 0 {
result = append(result, n)
}
}
This is a standard way to filter data.
2. Merging slices from multiple sources
combined := append(configDefaults, envOverrides...)
combined = append(combined, cliArgs...)
This is useful for configuration and layered inputs.
3. Copying before appending
safe := append([]string{}, original...)
safe = append(safe, "new-item")
Developers do this when they do not want to modify a slice that might be shared.
4. Guarding against unintended mutation
Even though append returns a new slice value, it may still reuse the original backing array. In shared code, developers sometimes create a fresh slice first to avoid accidental side effects.
Common Mistakes
1. Forgetting ... when appending a slice
Broken code:
append([]int{1, 2}, []int{3, 4})
Why it fails:
appendexpectsintvalues after the first argument.[]int{3, 4}is a slice, not individualintvalues.
Correct code:
append([]int{1, 2}, []int{3, 4}...)
2. Forgetting to assign the result of append
Broken code:
a := []int{1, 2}
append(a, 3, 4)
fmt.Println(a)
Why it is wrong:
Comparisons
| Concept | What it means | Example | When to use |
|---|---|---|---|
append(slice, x) | Append one element | append(a, 3) | Add a single value |
append(slice, x, y) | Append multiple elements | append(a, 3, 4) | Add several known values |
append(slice, anotherSlice...) | Append all elements from another slice | append(a, b...) | Concatenate slices |
copy(dst, src) | Copy elements from one slice into another | copy(dst, src) |
Cheat Sheet
Quick reference
Append single values
s = append(s, 1)
s = append(s, 2, 3)
Append one slice to another
s = append(s, other...)
Create a new combined slice
combined := append([]int{}, a...)
combined = append(combined, b...)
Important rules
appendworks with slices.appendreturns the updated slice.- Use
...to expand a slice into individual arguments. - Without
..., Go sees the second slice as one value, not many elements. appendmay reuse the original backing array.
Common error
append([]int{1, 2}, []{, })
FAQ
Why do I need ... when appending a slice in Go?
Because append expects individual elements, not a slice value. ... expands the slice into separate arguments.
Can I append one slice directly to another without ...?
No. Not with append. Without ..., Go treats the second slice as a single argument of type []int, which does not match the expected element type.
Does append modify the original slice?
It returns an updated slice. It may reuse the same underlying array or allocate a new one, depending on capacity.
What is the difference between append(a, b...) and append(a, 3, 4)?
If b is []int{3, 4}, then they are conceptually the same. b... expands into the individual values.
Can I concatenate slices of different types in Go?
No. The element types must match. For example, []int can only be appended with int values or another expanded with .
Mini Project
Description
Build a small Go program that merges two lists of task IDs into one combined list. This demonstrates how slice concatenation works in a realistic scenario where data may come from two different sources, such as a database query and an API response.
Goal
Create a program that combines two []int slices into a single result slice and prints the merged output.
Requirements
- Create two integer slices with sample task IDs.
- Combine the slices using
appendand the...operator. - Print the final combined slice.
- Also create a second version that preserves the original first slice by copying it first.
Keep learning
Related questions
Check if a Value Exists in a Slice in Go
Learn how to check whether a value exists in a slice in Go, and why Go has no Python-style `in` operator for arrays or slices.
Convert String to Integer in Go: Idiomatic Parsing with strconv.Atoi
Learn the idiomatic way to convert a string to an int in Go using strconv.Atoi, with examples, errors, and common mistakes.
Convert a Zero-Terminated Byte Array to String in Go
Learn how to convert a zero-terminated byte array to a Go string by trimming trailing null bytes safely and clearly.