map[gorm.DB]struct{}{} 给出无效的地图键类型 gorm.DB

Eug*_*sky 5 dictionary key go hashable go-gorm

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

var (
    autoMigrations map[gorm.DB]struct{}
)
Run Code Online (Sandbox Code Playgroud)

但是编译器不允许我用错误来做这个:invalid map key type gorm.DB. 我可以使用指向gorm.DBs 的指针来愚弄它,例如:

map[*gorm.DB]struct{}
Run Code Online (Sandbox Code Playgroud)

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

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

autoMigrations []gorm.DB
Run Code Online (Sandbox Code Playgroud)

但是我必须手动过滤元素,这似乎有点疯狂。

icz*_*cza 7

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

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

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)
Run Code Online (Sandbox Code Playgroud)

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

查看相关问题:

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

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

Go 中的结构集

  • 优秀的答案!Go 有没有定义自己的比较函数?像 Python 中的 `__hash__` 吗?这样我就可以让它们具有可比性。 (2认同)