45

I am using this construct to simulate a set

type MyType uint8
map[MyType]interface{}

I then add in all my keys and map them to nil.

I've learnt that it is also possible to use

map[MyType]struct{}

Any benefits of using the empty struct versus interface{}.

1

3 Answers 3

52

Memory usage. For example, types struct{}, interface{}, and bool,

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    var s struct{}
    fmt.Println(unsafe.Sizeof(s))
    var i interface{}
    fmt.Println(unsafe.Sizeof(i))
    var b bool
    fmt.Println(unsafe.Sizeof(b))
}

Output (bytes for 32-bit architecture):

0
8
1

Output (bytes for 64-bit architecture):

0
16
1

References:

Go Data Structures: Interfaces

Sign up to request clarification or add additional context in comments.

4 Comments

How does this affect the memory usage of the map? What will it allocate internally for a struct{} type for the values?
@DanielWilliams: A Go map stores key and element values. A struct{} element value occupies zero bytes.
I guess that leads into what happens with a map[struct{}]struct{}? It would have a zero sized key and a zero sized value but you could put 1 thing it (also zero sized).
@DanielWilliams: Use type bool instead of type map.
43

The empty struct and empty interface, though syntactically similar, are actually opposites. An empty struct holds no data; an empty interface can hold any type of value. If I see a map[MyType]struct{}, I know immediately that no values will be stored, only keys. If I see a map[MyType]interface{}, my first impression will be that it is a heterogenous collection of values. Even if I see code storing nil in it, I won't know for sure that some other piece of code doesn't store something else in it.

In other words, using struct{} makes your code much more readable. It also saves a little memory, as described in the other answer, but that is just a fringe benefit of using the right tool for the job.

2 Comments

What about map[MyType]bool?
I would actually tend to use map[MyType]bool myself, because it can be used directly in an if condition, and it would probably produce the most readable code. But the OP only asked about struct and interface, and I wanted to keep my answer simple. (And map[MyType]struct{} is a recognized idiom for sets.)
2

I would like to add additional detail about empty struct , as differences are already covered by andybalholm and peterSO .

Below is the example which shows usability of empty struct .

Creates an instance of rectangle struct by using a pointer address operator is denoted by & symbol.

package main

import "fmt"

type rectangle struct {
    length  int
    breadth int
    color   string
}

func main() {
    var rect1 = &rectangle{10, 20, "Green"} // Can't skip any value
    fmt.Println(rect1)

    var rect2 = &rectangle{}
    rect2.length = 10
    rect2.color = "Red"
    fmt.Println(rect2) // breadth skipped

    var rect3 = &rectangle{}
    (*rect3).breadth = 10
    (*rect3).color = "Blue"
    fmt.Println(rect3) // length skipped
}

Reference : https://www.golangprograms.com/go-language/struct.html

For a thorough read you can refer : https://dave.cheney.net/2014/03/25/the-empty-struct

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.