Slices are a fundamental data structure in Go as they allow us to work with collection of elements.
One of the most common tasks when working with slices is slice filtering.
Slicing filters is an essential technique for working with data collections such as arrays or slices. It allows us to extract specific elements from a slice based on certain criteria.
In this tutorial, we will walk you through the methods that you can use to accomplish this task.
Golang Slices
Before we dive into the process of removing duplicates from a slice, let us explore the basics of slices in case you are not familiar.
What Is a Slice?
In Go, a slice is a dynamically-sized, flexible view into an underlying array. It is a more versatile alternative to arrays as it can grow or shrink as needed without requiring us to specify a fixed size.
We can use slices to represent the sequences of data such as lists, collections, or arrays with dynamic sizes.
A slice is comprised of three main components in Go:
- Pointer to the underlying array
- Length (number of elements in the slice)
- Capacity (maximum number of elements that the slice can hold without resizing the underlying array)
The following shows the basic syntax of declaring a slice in Go:
Basics of Slices in Go
The first and most common method of creating a slice in Go is using the literal definition as shown in the following example:
We can also use the βmakeβ function to declare a new slice as demonstrated in the following example:
This should create a slice of integers with the length of 3 and a capacity of 5.
We can also create a slice by slicing an existing array as follows:
slice := arr[1:4]
This should create a new slice from the second and fourth elements of the array.
Adding Elements to Slice
In Go, we can add elements to an existing slice using the append() function as shown in the following example:
databases = append(databases, "Redis")
In the βappendβ function, we need to pass the existing slice and the new elements that we wish to add to the slice.
Accessing the Elements
We can access the slice elements using the elements index as shown in the following example:
This should return the first element in the slice.
Iterating Over Slice
We can use a basic βforβ loop to iterate over the elements of a slice as shown in the following example:
fmt.Printf("Index: %d, Value: %s\n", i, db)
}
Golang Filter Slice
Slice filtering involves selecting specific elements that match a specific condition and discarding the ones that do not.
1.Β Β Β Β Β Using the βForβ Loop
This is a basic and common method in data manipulation as shown in the following code example:
import (
"fmt"
)
func main() {
nums := []int{1012, 32, 32, 232, 212, 45, 2, 12, 64, 23, 54, 76, 872}
filtered := []int{}
for _, num := range nums {
if num%2 == 0 {
filtered = append(filtered, num)
}
}
fmt.Println(filtered)
}
This uses a based βforβ loop and condition checker to remove any elements that are not even numbers.
2.Β Β Β Β Β Using the Filter Package
For more advanced filtering operations, we can use the external packages like βgo-funkβ:
https://github.com/thoas/go-funk
This library provides helpers (map, find, contains, filter, and more).
import (
"fmt"
"github.com/thoas/go-funk"
)
func main() {
r := funk.Filter([]int{1, 10, 2, 8, 3, 7, 4, 6, 5, 9}, func(x int) bool {
return x%2 == 0
})
fmt.Println(r)
}
This uses the funk package to perform a filter and sort on the slice values.
3.Β Β Β Β Β Using Channels and Goroutines
For larger slices or complex filter conditions, we can use the goroutines and channels for concurrent filtering.
import (
"fmt"
)
func concurrentFilter(slice []int, condition func(int) bool) []int {
result := make([]int, 0)
ch := make(chan int)
for _, v := range slice {
go func(val int) {
if condition(val) {
ch <- val
} else {
ch <- -1
}
}(v)
}
for range slice {
val := <-ch
if val != -1 {
result = append(result, val)
}
}
return result
}
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
filtered := concurrentFilter(numbers, func(n int) bool { return n%2 == 0 })
fmt.Println(filtered)
}
This combines the power of goroutines and channels to provide a more complex and concurrent filtering.
Conclusion
In this tutorial, we covered the methods and techniques of performing the slice filtering from the basic βforβ loop to the advanced filtering using channels and goroutines.