How to Find the Difference Between Two Slices in Go
Go's standard library has no set type, so "difference between two slices" always means building the hash-lookup yourself - usually with a map. Here are the three approaches worth knowing, from the everyday idiom to the sorted two-pointer version for when memory matters more than a few extra lines.
Quick answer
Build a map[string]struct{} from slice b, then loop over slice a and keep any element not present in the map - this is the standard Go idiom and runs in roughly O(n + m). With Go 1.18+, wrap it in a generic function constrained to comparable so it works for any comparable type, not just strings. If both slices are already sorted, a two-pointer scan gets the same O(n + m) result without allocating a map.
Need the same thing in another language?
See the full reference for Python, JavaScript, SQL, Java, and more.
The map[string]struct{} idiom
a := []string{"apple", "banana", "cherry", "banana"}
b := []string{"banana", "date"}
setB := make(map[string]struct{}, len(b))
for _, v := range b {
setB[v] = struct{}{}
}
var aOnly []string
for _, v := range a {
if _, found := setB[v]; !found {
aOnly = append(aOnly, v)
}
}
fmt.Println(aOnly) // [apple cherry banana] - order preserved, duplicates preserved struct{}{} is the idiomatic value type for a "set" in Go - it takes zero bytes of storage, since the map is only being used for its key lookup, not to store any associated value. This approach preserves both the order of a and any duplicate elements it contains, unlike a true set-based difference.
A generic Difference function (Go 1.18+)
func Difference[T comparable](a, b []T) []T {
setB := make(map[T]struct{}, len(b))
for _, v := range b {
setB[v] = struct{}{}
}
var result []T
for _, v := range a {
if _, found := setB[v]; !found {
result = append(result, v)
}
}
return result
}
// Usage:
aOnly := Difference([]int{1, 2, 3}, []int{2, 3, 4}) // [1] The comparable constraint (built into Go, no import needed) allows this function to work with any type that supports == - strings, numbers, and structs made entirely of comparable fields all qualify, without writing a separate function per type.
Why slices.Contains alone isn't enough
import "slices"
var aOnly []string
for _, v := range a {
if !slices.Contains(b, v) {
aOnly = append(aOnly, v)
}
}
// Works, but slices.Contains is O(n) per call - the loop is O(n * m) overall The standard library slices package (Go 1.21+) has no set-difference helper. slices.Contains does a linear scan each time it's called, so using it inside a loop over the other slice reintroduces the O(n * m) cost the map idiom exists to avoid - fine for small slices, worth replacing with a map for anything sizeable.
Sorted two-pointer scan: no map allocation
sort.Strings(a)
sort.Strings(b)
var aOnly []string
i, j := 0, 0
for i < len(a) {
if j >= len(b) || a[i] < b[j] {
aOnly = append(aOnly, a[i])
i++
} else if a[i] > b[j] {
j++
} else {
i++
j++
}
} Walking both sorted slices with two pointers finds the difference in a single O(n + m) pass with no map allocation at all - useful when memory is tighter than CPU time, or the slices are already sorted for another reason. If they aren't already sorted, sorting first costs O(n log n), at which point the map idiom is usually simpler to write for a one-off comparison.
Just need the answer, not the code? Paste both lists.
Open Compare 2 Lists →Frequently Asked Questions
Does Go have a built-in set type for comparing slices?
map[T]struct{}, using an empty struct as the value since it takes zero bytes of storage - it exists purely to give you O(1) key lookups via the map.Why use map[string]struct{} instead of map[string]bool?
struct{}{} occupies zero bytes, while bool occupies one byte per entry. For large slices this adds up in memory, and semantically struct{}{} communicates "this is a set, the value carries no information" more clearly than a bool that's always true.How do I write a generic difference function in Go?
func Difference[T comparable](a, b []T) []T, constrained to the built-in comparable interface so it works with any type that supports == - strings, ints, and structs of comparable fields all qualify.Does the slices package have a difference function?
slices package (Go 1.21+) has slices.Contains, slices.Index, and similar helpers, but no set-difference function. slices.Contains is a linear O(n) scan, so calling it inside a loop over another slice reintroduces the O(n * m) problem the map idiom avoids.