Introduction

Welcome to our Simulating Sets in Go lesson! In Go, there's no built-in type specifically called a "set." However, the concept of a set — a collection that stores unique elements — can be emulated using other data structures provided by the language, such as maps. Sets are incredibly useful when you need to ensure that elements in a collection are unique. In this lesson, you'll explore how to create and manage set-like collections in Go by implementing a Set custom struct.

Creating and Manipulating Sets

In Go, we can simulate a set by leveraging maps. A map's keys naturally represent unique elements due to their uniqueness within the context of the map. Below, we'll demonstrate how to create and manipulate a set-like structure using a custom Set struct.

In this example, the Set struct encapsulates the map, ensuring element uniqueness. The choice of using struct{} as the map's value type is intentional—it occupies no memory (0 bytes), unlike other types such as bool. This design decision leverages memory efficiency.

Inserting and Deleting Elements

To simulate basic set operations, we define receiver functions (methods) for the Set struct:

  • Inserting an Element: The Add() method updates the map with the key being the element and value as an empty struct, ensuring the element's existence in the set.
  • Deleting an Element: The Remove() method removes the element by deleting its key from the map.
  • Checking for Membership: The Has() method checks for the presence of a key in the map, hence confirming an element's membership in the set.
Set Operations: Union

We can simulate common set operations such as union, intersection, and difference by implementing additional methods for the Set struct.

The union of two sets involves combining the elements of both sets into a new set.

In the Union method, we iterate over the elements of both sets and add them to a new Set. This ensures that all unique elements from both sets are collected into the result, providing a union of the two sets.

Set Operations: Intersection

The intersection of two sets results in a set containing only elements present in both sets.

The Intersect method works by iterating over the elements of the first set and checking if each element is present in the second set. If an element exists in both, it is added to the result set, yielding the intersection.

Set Operations: Difference

The difference between two sets results in a set containing elements that are in the first set but not in the second.

For the Difference method, we check each element from the first set to see if it does not exist in the second set. Those elements which are exclusive to the first set are added to the result, forming the difference.

Immutable Sets

Although Go doesn't have an explicit mechanism for immutability, we can use techniques such as returning read-only views of the set or encapsulating the set in a function that only provides read access.

In the immutable set implementation, we construct a ImmutableSet struct that encapsulates a map, similar to the mutable set. However, the operations provided only allow read access, such as checking if an element is contained in the set through the Contains method. This design encapsulates the data and does not allow modifications, providing a layer of immutability by restricting operations.

Performance Benefits of Sets

Creating set-like structures using maps offers efficient membership tests. Maps in Go provide constant time complexity on average (O(1)) for membership checks compared to slices, which require a linear search (O(n)). Let's benchmark the execution time for both data structures using Go's testing module:

Running the above benchmark with go test -bench . produces a result similar to the following, highlighting the huge difference in terms of efficiency (ns/op represents the time taken in nanoseconds for that operation):

Lesson Summary

Congratulations! You've learned how to create and manipulate set-like structures in Go by implementing a custom Set struct, perform set operations, and understand the performance benefits. Practice these concepts to reinforce your understanding. Happy coding!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal