Implement a Custom Append Function in Go
Go's built-in append function is a cornerstone for working with slices, providing a convenient way to add elements. This challenge asks you to reimplement a similar append functionality from scratch for a slice of integers, understanding the underlying mechanics of slice growth and element addition.
Problem Description
Your task is to create a Go function named customAppend that mimics the behavior of the standard append function for slices of integers. This function should take an existing slice of integers and one or more integers to append to it, returning a new slice with the appended elements.
Key Requirements:
- The
customAppendfunction should accept a slice of integers ([]int) as its first argument and a variable number of integers (...int) as subsequent arguments. - It must return a new slice (
[]int) containing all the elements of the original slice followed by the new elements. - The function should correctly handle cases where the underlying array of the original slice needs to be reallocated (i.e., when the capacity is insufficient).
- The original slice should not be modified directly if a reallocation occurs; a new slice should be returned.
Expected Behavior:
- If the original slice has enough capacity, the new elements are added to the existing underlying array, and a new slice header pointing to this modified array is returned.
- If the original slice does not have enough capacity, a new, larger underlying array will be allocated, the existing elements will be copied to this new array, followed by the new elements. A slice header pointing to this new array will be returned.
Edge Cases:
- Appending to an empty slice.
- Appending multiple elements at once.
- Appending to a slice that is already at full capacity.
Examples
Example 1:
Input:
originalSlice := []int{1, 2, 3}
elementsToAppend := 4, 5
Output:
[]int{1, 2, 3, 4, 5}
Explanation: The function appends 4 and 5 to the existing slice. Since the initial slice likely has some spare capacity, the elements are added efficiently.
Example 2:
Input:
originalSlice := []int{}
elementsToAppend := 10, 20
Output:
[]int{10, 20}
Explanation: Appending to an empty slice creates a new slice with the provided elements.
Example 3:
Input:
originalSlice := make([]int, 3, 3) // Slice with length 3 and capacity 3
originalSlice[0] = 1
originalSlice[1] = 2
originalSlice[2] = 3
elementsToAppend := 4, 5
Output:
[]int{1, 2, 3, 4, 5}
Explanation: Here, the original slice has zero spare capacity. `customAppend` will need to allocate a new, larger underlying array to accommodate the new elements and copy the existing ones over. The returned slice will be a new slice pointing to this new array.
Constraints
- The input slice will be of type
[]int. - The elements to append will be of type
int. - The function should not rely on the built-in
appendfunction for its core logic of adding elements or reallocating capacity. You may usemaketo allocate new arrays. - Performance is important; consider the efficiency of copying elements when reallocating.
Notes
Think about how Go slices are structured: a pointer to an underlying array, a length, and a capacity. Your customAppend function needs to manage these aspects. Consider how the length and capacity change when elements are added, especially when a new underlying array is required. You might find it useful to inspect the len() and cap() of slices.