I really like google golang but could some one explain what the rationale is for the implementors having left out a basic data structure such as sets from the standard library?
-
8The language is actually called Go, not golang – daniel gratzer Nov 28 '12 at 02:44
-
103But "golang" is more searchable – Matt May 29 '13 at 19:27
-
24Way more searchable. Googling "go set" returns images of a wooden board with black and white pieces. – Doug Richardson Feb 10 '14 at 05:55
-
I believe the community advice is to use Golang, not Go, for the above reasons - searchability – occulus Dec 13 '19 at 11:58
3 Answers
One potential reason for this omission is that it's really easy to model sets with a map.
To be honest I think it's a bit of an oversight too, however looking at Perl, the story's exactly the same. In Perl you get lists and hashtables, in Go you get arrays, slices, and maps. In Perl you'd generally use a hashtable for any and all problems relating to a set, the same is applicable to Go.
Example
to imitate a set ints in Go, we define a map:
set := make(map[int]bool)
To add something is as easy as:
i := valueToAdd()
set[i] = true
Deleting something is just
delete(set, i)
And the potential awkwardness of this construct is easily abstracted away:
type IntSet struct {
set map[int]bool
}
func (set *IntSet) Add(i int) bool {
_, found := set.set[i]
set.set[i] = true
return !found //False if it existed already
}
And delete and get can be defined similarly, I have the complete implementation here . The major disatvantage here is the fact that go doesn't have generics. However it is possible to do this with interface{}
in which case you'd have cast the results of get.

- 11,678
- 3
- 46
- 51
-
I've seen comments by Go authors suggestion that generics are a hoped-for feature, there being a hurdle in the way of needing to work out what the best idomatic pattern should be before committing to extending the language. – Rick-777 Apr 16 '13 at 17:49
-
3Here's my slightly-revised version with Contains and Size methods: http://play.golang.org/p/tDdutH672- – Rick-777 Apr 16 '13 at 18:07
-
How does this approach work for user defined set-values? And does it lend itself to an easy implementation of intersections/unions etc.? – Thomas Ahle Nov 26 '13 at 22:12
-
22Instead of `map[int]bool` one can use `map[int]struct{}` instead. I prefer the last. – oblitum Dec 11 '13 at 02:26
-
22
-
4https://github.com/fatih/set is an implementation of my based on maps and empty structs. It's thread safe and has a simple api. – Fatih Arslan Jan 11 '14 at 23:50
-
6With `map[int]struct{}` you can't do `if mymap["key"] {` to check for membership. Google [recommends using `bool`](https://golang.org/doc/effective_go.html) (search for "A set can be implemented"). – Timmmm Jan 06 '15 at 13:18
-
3
-
1
-
@Timmmm: "A set can be implemented as a map with value type `bool`." is far from being the same as "Google recommends using `bool` [instead of `struct{}` for the value type of a map as a set]." Also note that the key point of the paragraph containing the quoted sentence is the zero return value for nonexistent entries, and that `map[T]bool` is an example where that property can be useful. – musiphil Aug 22 '16 at 17:04
I think this has to do with golang
focus on simplicity. set
s become really useful with difference
, intersection
, union
, issubset
, and so on.. methods. Perhaps golang
team felt that it is too much for one data structure. But otherwise a "dumb set" that only has add
, contains
and remove
can be easily replicated with map
as explained by @jozefg.

- 425
- 1
- 3
- 10
-
i disagree. a set is mostly used for membership checks and uniqeness semantics. a set implementation would be perfectly usable without those methods. that being said, they are also trivial to implement. – Sedat Kapanoglu Aug 17 '18 at 18:23
The previous answer works ONLY IF the key are a built-in type. To complement the previous answer, here is a way to implement a set whose elements are user-defined types:
package math
// types
type IntPoint struct {
X, Y int
}
// set implementation for small number of items
type IntPointSet struct {
slice []IntPoint
}
// functions
func (p1 IntPoint) Equals(p2 IntPoint) bool {
return (p1.X == p2.X) && (p1.Y == p2.Y)
}
func (set *IntPointSet) Add(p IntPoint) {
if ! set.Contains(p) {
set.slice = append(set.slice, p)
}
}
func (set IntPointSet) Contains(p IntPoint) bool {
for _, v := range set.slice {
if v.Equals(p) {
return true
}
}
return false
}
func (set IntPointSet) NumElements() int {
return len(set.slice)
}
func NewIntPointSet() IntPointSet {
return IntPointSet{(make([]IntPoint, 0, 10))}
}

- 145
- 2
-
8"works ONLY IF the key are a built-in type" is **wrong**. `type mySet map[IntPoint]bool` works perfectly well. All that is required of the key type used in a map is [that it has `==` and `!=`](https://golang.org/ref/spec#Map_types). Equality of struct types is well defined, your `Equals` method should be just `p1 == p2`. – Dave C Mar 27 '15 at 01:48
-
1It is true that equality for structs is well-defined, but if the struct contains maps or slices as fields, they will be compared by reference, rather than by value. This may not be what you want. – Chaim-Leib Halbert Oct 24 '18 at 19:42
-
1I take a bit of issue with this solution, because `Contains` takes linear time, while `aMap[]` takes constant time, regardless the number of members. A better solution would internally create a unique key based the contents of each member, and leverage the constant-time querying that the `map` type provides. Even faster solutions that consider cache behavior, etc. exist as well. – Chaim-Leib Halbert Oct 24 '18 at 19:46