Reputation: 12845
I'd like to create a "set" of gorm types used in my application. So I'd like to define a map
with my types gorm.DB
as keys and empty structs{}
as flags:
var (
autoMigrations map[gorm.DB]struct{}
)
But compiler doesn't allow me do this with error: invalid map key type gorm.DB
. I can fool it using pointers to gorm.DB
s like:
map[*gorm.DB]struct{}
But it's not a solution, because I need to make it unique and if my map gets filled like db.AutoMigrate(&Chat{})
I can get lots of similar object with different addresses.
Another solution is to make a slice of gorm.DB
:
autoMigrations []gorm.DB
But I have to filter elements on addition manually, which seems insane a little bit.
Upvotes: 6
Views: 7082
Reputation: 417702
You can only use types as keys in a map that are comparable. Spec: Map types:
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.
gorm.DB
is a struct, and struct values are only comparable if all their fields are comparable:
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
But gorm.DB
has e.g. a DB.values
field which is a map type, and maps are not comparble, and thus gorm.DB
values are not comparable either, and so you can't use it as map keys.
If you want to create a set of types, you should use reflect.Type
as the map keys, which you can acquire using reflect.TypeOf()
from a value of that type.
A little trick, if you want a reflect.Type
without having to create a value of the type in question, you can start from a pointer value of that type (which may be nil
), and use Type.Elem()
to get the reflect.Type
descriptor of the pointed type.
For example, to get the reflect.Type
descriptor of a struct type Point struct{ X, Y int }
without actually creating / having a Point
:
type Point struct{ X, Y int }
tpoint := reflect.TypeOf((*Point)(nil)).Elem()
fmt.Println(tpoint)
Which prints main.Point
. Try it on the Go Playground.
See related questions:
How can I prevent a type being used as a map key?
Why can't Go slice be used as keys in Go maps pretty much the same way arrays can be used as keys?
Upvotes: 9