Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you have a map with no value in go?

I ask since I like that maps do not allow multiple keys. I know you can do something like the below where your values are bools or empty struct, but is there a way to get around specifying any value for your keys? Is there some advantage to having to specify an empty struct?

Related question, but focused on appending only unique values.

type N struct {}

func tengoQueCagar() {
    var map_almost_empty_value1 = map[int]bool{0:true,1:false}
    var map_almost_empty_value2 = map[int]struct{}{0:struct{}{},1:struct{}{}} //long and seems like lame syntax...
    var map_almost_empty_value3 = map[int]N{0:N{},1:N{}} //shorter.. better?

    var map_not_possible_empty_value_2 = map[int]nil{0:nil,1:nil} // better than empty struct syntax... but not possible
    var map_not_possible_empty_value_2 = map[int]{0,1} // ideally possible... but not... 

    //do something...
}
like image 745
John Drinane Avatar asked Nov 29 '22 08:11

John Drinane


2 Answers

struct{} requires 0 bytes to store. If you declare a map with struct{} values, you'd only be storing map keys.

There's a nice blog post about it: https://dave.cheney.net/2014/03/25/the-empty-struct

If you want to use a map like a set, it might help to declare a separate type for it:

type IntSet map[int]struct{}

And you can add some convenience methods to it, such as:

func (i IntSet) Has(v int) bool {
  _, ok := i[v]
  return ok
}
like image 57
Burak Serdar Avatar answered Dec 10 '22 13:12

Burak Serdar


For a direct answer to your question: See below!

This "empty struct{} as map values trick" comes up often and the argument in favor is always of the form "so the values do not need storage space".

The other natural thing to do is use a map[int]bool.

If memory is really a constraint of your application (e.g. because you are storing millions or billions of keys in your map) then yes: use struct{}. For all other, normal cases: Using struct{} makes such map literals awkward and key lookup more complicated as you have to use the comma-ok-variant (if _,ok := m[k]; ok {.

For bool values you can do a simple m[k] which is less to type and is easier to understand.

Personally I think use of struct{} as map value is a unnecessary, premature, overly clever optimisation. If you really need to save these few bytes because your map will contain millions of entries then probably a map is not the right data structure anyway: Depending on the use case bit vectors, sparse data structures or even probabilistic data structures (bloom-, cuckoo-filters), union-find, etc. might be much better suited.

Answer: No. In a map literal you have to specify each and every key. (General rule of thumb: There is no syntactic sugar in Go; there are no clever shortcuts in Go; everything is explicit in Go.)

like image 36
Volker Avatar answered Dec 10 '22 13:12

Volker