Golang slices.Compact
last modified April 20, 2025
This tutorial explains how to use the slices.Compact
function in Go.
We'll cover slice operations with practical examples of removing duplicates.
The slices.Compact function replaces consecutive runs of equal elements with a single copy. It's part of Go's experimental slices package.
This function is useful for cleaning up data by removing adjacent duplicates. It modifies the slice in place and returns the new length of the slice.
Basic slices.Compact Example
The simplest use of slices.Compact
removes consecutive duplicates
from a slice of integers. The function modifies the original slice.
package main import ( "fmt" "slices" ) func main() { numbers := []int{1, 1, 2, 2, 3, 3, 3, 4} newLength := slices.Compact(numbers) numbers = numbers[:newLength] fmt.Println("Compacted numbers:", numbers) }
We create a slice with consecutive duplicates. After compacting, only unique consecutive values remain. The slice is shortened to the new length.
Working with Strings
slices.Compact
works with string slices too. This example removes
consecutive duplicate words from a slice.
package main import ( "fmt" "slices" ) func main() { words := []string{"hello", "hello", "world", "go", "go", "go"} newLength := slices.Compact(words) words = words[:newLength] fmt.Println("Compacted words:", words) }
The function compares strings and removes consecutive duplicates. Note that non-consecutive duplicates remain in the slice.
Custom Comparison Function
slices.CompactFunc
allows custom comparison logic. This example
compacts case-insensitive string duplicates.
package main import ( "fmt" "slices" "strings" ) func main() { words := []string{"Hello", "hello", "World", "world", "Go"} newLength := slices.CompactFunc(words, func(a, b string) bool { return strings.EqualFold(a, b) }) words = words[:newLength] fmt.Println("Case-insensitive compact:", words) }
We use strings.EqualFold
for case-insensitive comparison. The
function removes consecutive words that match regardless of case.
Working with Structs
We can compact slices of custom struct types. This example removes consecutive people with the same age.
package main import ( "fmt" "slices" ) type Person struct { Name string Age int } func main() { people := []Person{ {"Alice", 25}, {"Bob", 25}, {"Charlie", 30}, {"Dave", 30}, {"Eve", 30}, } newLength := slices.CompactFunc(people, func(a, b Person) bool { return a.Age == b.Age }) people = people[:newLength] fmt.Println("Compacted people:", people) }
The custom comparison function checks only the Age field. Consecutive people with the same age are removed, keeping only the first occurrence.
Empty Slice Behavior
slices.Compact
handles empty slices gracefully. This example
demonstrates its behavior with empty and nil slices.
package main import ( "fmt" "slices" ) func main() { var empty []int nilSlice := []string(nil) emptyLen := slices.Compact(empty) nilLen := slices.Compact(nilSlice) fmt.Println("Empty slice length:", emptyLen) fmt.Println("Nil slice length:", nilLen) }
Both empty and nil slices return length 0. The function safely handles these edge cases without modification.
Performance Considerations
For large slices, compacting can be memory efficient. This example benchmarks the operation on a large slice.
package main import ( "fmt" "slices" "time" ) func main() { largeSlice := make([]int, 1_000_000) for i := range largeSlice { largeSlice[i] = i % 10 // Creates many consecutive duplicates } start := time.Now() newLength := slices.Compact(largeSlice) largeSlice = largeSlice[:newLength] fmt.Println("Compacted length:", newLength) fmt.Println("Time taken:", time.Since(start)) }
The operation is efficient as it works in-place. Memory usage remains constant regardless of input size, only modifying the existing slice.
Practical Example: Log Deduplication
This practical example uses slices.Compact
to remove consecutive
duplicate log entries while preserving order.
package main import ( "fmt" "slices" ) func main() { logs := []string{ "ERROR: Disk full", "ERROR: Disk full", "INFO: Backup started", "WARNING: High CPU usage", "WARNING: High CPU usage", "WARNING: High CPU usage", "INFO: Backup completed", } newLength := slices.Compact(logs) logs = logs[:newLength] fmt.Println("Deduplicated logs:") for _, log := range logs { fmt.Println(log) } }
Consecutive duplicate log messages are removed while maintaining the original order. This helps reduce log noise while preserving important sequence.
Source
Go experimental slices package documentation
This tutorial covered the slices.Compact
function in Go with practical
examples of removing consecutive duplicates from slices in various scenarios.
Author
List all Go tutorials.