Understanding Slice Passing and Append in Golang
James Reed
Infrastructure Engineer · Leapcell
![Cover of "Understanding Slice Passing and Append in Golang"](https://cdn1.leapcell.io/117083021ad9df20f-89b4-462c-9d2e-727e1448e15f.png)
In Go, slices are a powerful and flexible data structure that provide a dynamic interface to arrays. Understanding how to pass slices to functions and effectively use the append
function is crucial for efficient Go programming.
Key Takeaways
- Passing a slice to a function copies the slice header, but both point to the same underlying array.
- Modifying a slice within a function affects the original unless
append
triggers a new allocation. - The
append
function may allocate a new array if the existing capacity is exceeded.
Passing Slices to Functions
When you pass a slice to a function in Go, you're passing a copy of the slice header, not the underlying array. This means that while the function receives its own copy of the slice header (which includes the pointer to the underlying array, length, and capacity), both the original and the function's copy point to the same underlying array. Consequently, modifications to the elements of the slice within the function affect the original slice.
However, if you modify the slice itself within the function—such as by appending new elements—the function's copy of the slice header may point to a new underlying array if the existing array doesn't have sufficient capacity. In this case, the original slice remains unchanged. To reflect such modifications in the original slice, you can return the modified slice from the function and reassign it, or pass a pointer to the slice.
Example: Modifying a Slice Within a Function
package main import "fmt" func modifySlice(s []int) { s[0] = 10 // Modifies the first element; affects the original slice s = append(s, 20) // Appends a new element; may not affect the original slice if capacity is exceeded fmt.Println("Inside function:", s) } func main() { nums := []int{1, 2, 3} modifySlice(nums) fmt.Println("Outside function:", nums) }
Output:
Inside function: [10 2 3 20]
Outside function: [10 2 3]
In this example, the modification of s[0]
affects the original slice nums
. However, the append
operation may result in s
pointing to a new underlying array if the original array's capacity is exceeded, leaving nums
unchanged outside the function.
Using the append
Function
The built-in append
function in Go is used to add elements to the end of a slice. If the slice has sufficient capacity, the elements are added to the existing array. If not, a new array is allocated, and the elements are added to it. The append
function returns the updated slice, which may point to a new underlying array.
Syntax:
newSlice := append(originalSlice, elements...)
Example: Appending Elements to a Slice
package main import "fmt" func main() { nums := []int{1, 2, 3} nums = append(nums, 4, 5) fmt.Println(nums) // Output: [1 2 3 4 5] }
To append one slice to another, use the ...
operator to unpack the elements of the second slice:
package main import "fmt" func main() { slice1 := []int{1, 2, 3} slice2 := []int{4, 5, 6} slice1 = append(slice1, slice2...) fmt.Println(slice1) // Output: [1 2 3 4 5 6] }
FAQs
Direct modifications to elements affect the original, but append
may allocate a new array, isolating changes.
Return the modified slice and reassign it or pass a pointer to the slice.
Go allocates a new array, copies elements, and updates the slice header to point to the new array.
In this example, slice2...
unpacks the elements of slice2
, and append
adds them to slice1
.
Key Takeaways
-
Passing a slice to a function copies the slice header, but both the original and the copy point to the same underlying array.
-
Modifying the elements of a slice within a function affects the original slice.
-
Appending to a slice within a function may not affect the original slice if the underlying array's capacity is exceeded, as
append
may allocate a new array. -
To ensure changes to a slice within a function are reflected in the original, return the modified slice and reassign it, or pass a pointer to the slice.
Understanding these behaviors is essential for effective slice manipulation in Go.
We are Leapcell, your top choice for hosting Go projects.
Leapcell is the Next-Gen Serverless Platform for Web Hosting, Async Tasks, and Redis:
Multi-Language Support
- Develop with Node.js, Python, Go, or Rust.
Deploy unlimited projects for free
- pay only for usage — no requests, no charges.
Unbeatable Cost Efficiency
- Pay-as-you-go with no idle charges.
- Example: $25 supports 6.94M requests at a 60ms average response time.
Streamlined Developer Experience
- Intuitive UI for effortless setup.
- Fully automated CI/CD pipelines and GitOps integration.
- Real-time metrics and logging for actionable insights.
Effortless Scalability and High Performance
- Auto-scaling to handle high concurrency with ease.
- Zero operational overhead — just focus on building.
Explore more in the Documentation!
Follow us on X: @LeapcellHQ