Issue
If I have a number of structs that I want to store:
type Stuff struct {
a string
b string
}
I can do it with a slice, but it seems like it would use less memory to use a proper set structure.
Unfortunately Go doesn’t have a set structure. Everyone recommends using map[Stuff]struct{}
but that doesn’t work because Stuff
is a struct. Anyone have any good solutions? Ideally without having to download a library.
Solution
Usually set and map data structures require more memory than storing a list of values in plain array or slice as set and map provide additional features efficiently like uniqueness or value retrieval by key.
If you want minimal memory usage, simply store them in a slice, e.g. []Stuff
. If you use the values in multiple places, it might also be profitable to just store their pointers, e.g. []*Stuff
and so each places that store the same Stuff
values can store the same pointer (without duplicating the value).
If you only want to store unique struct values, then indeed the set would be the most convenient choice, in Go realized with a map
.
There’s nothing wrong with map[Stuff]struct{}
, it works. The requirement for the key type for maps:
The comparison operators == and != must be fully defined for operands of the key type; thus the key type must not be a function, map, or slice.
Stuff
is a struct, and structs in Go are comparable if:
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
If your Stuff
struct is what you posted, it is comparable: it only contains fields of the comparable type string
.
Also note that if you want a set data structure, it’s clearer if you use bool
as the value type (e.g. map[Stuff]bool
) and true
as the value, and then you can simply use indexing to test if a value is in the map as the index expression yields the zero value of the value type (false
for bool
) if the key (Stuff
in your case) is not in the map, properly telling the value you’re looking for is not in the “set”. (And if it is in the map, its associated true
value is the result of the index expression – properly telling it is in the map).
Answered By – icza
Answer Checked By – David Marino (GoLangFix Volunteer)