Golang slices.EqualFunc
last modified April 20, 2025
This tutorial explains how to use the slices.EqualFunc
function in Go.
We'll cover slice comparison with custom equality functions through examples.
The slices.EqualFunc function compares two slices using a custom equality function. It's part of Go's experimental slices package.
This function is useful when you need custom comparison logic between slice elements. It returns true only if all corresponding elements are equal.
Basic slices.EqualFunc Example
The simplest use of slices.EqualFunc
compares two integer slices.
We define an equality function that checks if numbers are equal.
package main import ( "fmt" "slices" ) func main() { nums1 := []int{1, 2, 3} nums2 := []int{1, 2, 3} equal := slices.EqualFunc(nums1, nums2, func(a, b int) bool { return a == b }) fmt.Println("Slices are equal:", equal) }
We create two identical slices and compare them. The anonymous function defines our equality condition for each pair of elements.
Case-Insensitive String Comparison
slices.EqualFunc
can compare strings case-insensitively. This example
checks if two string slices contain the same words regardless of case.
package main import ( "fmt" "slices" "strings" ) func main() { words1 := []string{"Apple", "Banana"} words2 := []string{"apple", "banana"} equal := slices.EqualFunc(words1, words2, func(a, b string) bool { return strings.EqualFold(a, b) }) fmt.Println("Case-insensitive equal:", equal) }
The test function uses strings.EqualFold
for case-insensitive
comparison. The slices are considered equal despite different casing.
Comparing Structs by Field
We can use slices.EqualFunc
with custom struct types. This example
compares slices of Person structs by their Age field.
package main import ( "fmt" "slices" ) type Person struct { Name string Age int } func main() { group1 := []Person{ {"Alice", 25}, {"Bob", 30}, } group2 := []Person{ {"Charlie", 25}, {"Dana", 30}, } equal := slices.EqualFunc(group1, group2, func(a, b Person) bool { return a.Age == b.Age }) fmt.Println("Groups have same ages:", equal) }
The function compares only the Age fields, ignoring names. The slices are equal as their age sequences match.
Floating-Point Comparison with Tolerance
For floating-point numbers, exact equality is often problematic. This example uses a tolerance-based comparison.
package main import ( "fmt" "math" "slices" ) func main() { floats1 := []float64{1.0, 2.0, 3.0} floats2 := []float64{1.0000001, 1.9999999, 3.0000001} equal := slices.EqualFunc(floats1, floats2, func(a, b float64) bool { return math.Abs(a-b) < 0.0001 }) fmt.Println("Floats equal within tolerance:", equal) }
The comparison uses a small epsilon value to account for floating-point imprecision. The slices are considered equal despite tiny differences.
Comparing Different Types
slices.EqualFunc
can compare slices of different but compatible
types. This example compares integers with their string representations.
package main import ( "fmt" "slices" "strconv" ) func main() { nums := []int{1, 2, 3} strs := []string{"1", "2", "3"} equal := slices.EqualFunc(nums, strs, func(n int, s string) bool { return strconv.Itoa(n) == s }) fmt.Println("Numbers match strings:", equal) }
The function converts integers to strings for comparison. The slices are equal as their values correspond despite different types.
Empty and Nil Slice Behavior
slices.EqualFunc
handles empty and nil slices specially. This
example demonstrates various edge cases.
package main import ( "fmt" "slices" ) func main() { var nilSlice []int emptySlice := []int{} dataSlice := []int{1, 2, 3} // Nil vs empty fmt.Println("Nil == empty:", slices.EqualFunc(nilSlice, emptySlice, func(a, b int) bool { return a == b })) // Nil vs nil fmt.Println("Nil == nil:", slices.EqualFunc(nilSlice, nilSlice, func(a, b int) bool { return a == b })) // Empty vs data fmt.Println("Empty == data:", slices.EqualFunc(emptySlice, dataSlice, func(a, b int) bool { return a == b })) }
Nil and empty slices are considered equal to each other but not to non-empty slices. The comparison function is never called for empty/nil slices.
Practical Example: Database Results Comparison
This practical example compares database query results while ignoring certain fields like timestamps or IDs.
package main import ( "fmt" "slices" "time" ) type User struct { ID int Username string Email string CreatedAt time.Time } func main() { // Simulated database results dbResult1 := []User{ {1, "alice", "alice@example.com", time.Now()}, {2, "bob", "bob@example.com", time.Now()}, } dbResult2 := []User{ {3, "alice", "alice@example.com", time.Now().Add(time.Hour)}, {4, "bob", "bob@example.com", time.Now().Add(time.Hour)}, } equal := slices.EqualFunc(dbResult1, dbResult2, func(a, b User) bool { return a.Username == b.Username && a.Email == b.Email }) fmt.Println("User data matches (excluding IDs/timestamps):", equal) }
We compare user data while ignoring automatically generated fields. This demonstrates a real-world use case for custom equality logic.
Source
Go experimental slices package documentation
This tutorial covered the slices.EqualFunc
function in Go with
practical examples of custom slice comparison in various scenarios.
Author
List all Go tutorials.