5

我想创建一个在我的应用程序中使用的“一组”gorm 类型。所以我想定义一个map我的类型gorm.DB作为键和空structs{}作为标志:

var (
    autoMigrations map[gorm.DB]struct{}
)

但是编译器不允许我这样做时出现错误:invalid map key type gorm.DB. 我可以使用指向gorm.DBs 的指针来欺骗它,例如:

map[*gorm.DB]struct{}

但这不是一个解决方案,因为我需要使它独一无二,如果我的地图被填满,就像db.AutoMigrate(&Chat{})我可以得到许多具有不同地址的类似对象一样。

另一种解决方案是制作一片gorm.DB

autoMigrations []gorm.DB

但是我必须手动过滤添加元素,这看起来有点疯狂。

4

1 回答 1

8

您只能将类型用作 map 中可比较的键。规格:地图类型:

比较运算符== 和 != 必须为键类型的操作数完全定义;因此键类型不能是函数、映射或切片。

gorm.DB是一个结构,并且结构值只有在它们的所有字段都可比较时才可比较:

如果结构值的所有字段都是可比较的,则结构值是可比较的。如果它们对应的非空白字段相等,则两个结构值相等。

但是gorm.DB有例如一个DB.values映射类型的字段,并且映射不可比较,因此gorm.DB值也不可比较,因此您不能将其用作映射键。

如果要创建一组类型,则应将reflect.Type其用作映射键,您可以reflect.TypeOf()从该类型的值中获取这些键。

一个小技巧,如果您想要 areflect.Type而不必创建相关类型的值,您可以从该类型的指针值(可能是nil)开始,并使用Type.Elem()来获取reflect.Type指向类型的描述符。

例如,要获取reflect.Type结构类型的描述符Point struct{ X, Y int }而不实际创建/具有Point

type Point struct{ X, Y int }
tpoint := reflect.TypeOf((*Point)(nil)).Elem()
fmt.Println(tpoint)

哪个打印main.Point在Go Playground上尝试一下。

查看相关问题:

如何防止类型被用作映射键?

为什么 Go 切片不能用作 Go 映射中的键,就像数组可以用作键一样?

Go 中的结构集

于 2017-11-08T09:11:31.623 回答