Gorm 1.25.7 Error When Using joins and preload Together to Fetch a List: reflect: call of reflect.Value.Field on slice Value
内容提要
当join与preload是同一个表时,使用gorm v1.25.7会触发错误。解决办法是将gorm回滚至v1.25.6版本。
延伸解读
问题触发条件
该错误仅在特定组合下出现:Joins 与 Preload 指向同一张表,且查询结果使用切片接收。例如 db.Where("type = 2").Joins("A").Preload("A.B").Find(&a) 中,a 为 []A 类型。若缺少任一条件,可能不会触发此问题。
错误根源
GORM v1.25.7 的 preload.go 第 124 行使用 rel.Field.ReflectValueOf 获取 db.Statement.ReflectValue 的字段。但 Find(&a) 传入的是切片,ReflectValue 为 slice 类型,导致反射调用 Field 方法失败,从而抛出 reflect: call of reflect.Value.Field on slice Value。
临时解决方案
截至 2024 年 3 月 4 日,官方尚未修复该问题。可行的办法是在 go.mod 中将 GORM 版本回滚至 v1.25.6,该版本不存在此反射错误。回滚后需重新运行 go mod tidy 并验证相关查询是否正常。
Q&A
Gorm 1.25.7 在什么情况下会触发 'reflect: call of reflect.Value.Field on slice Value' 错误?
当 join 与 preload 是同一个表时,使用 gorm v1.25.7 会触发该错误。例如代码:db.where("type = 2").Joins("A").Preload("A.B").Find(&a)。
Gorm 1.25.7 这个错误的完整报错信息是什么?
报错信息为:reflect: call of reflect.Value.Field on slice Value。
为什么 Gorm 1.25.7 会出现这个 reflect 错误?
错误原因是源码 preload.go:124 使用了 rel.Field.ReflectValueOf 获取 db.Statement.ReflectValue,但 Find(&a) 传入的是 slice 类型,导致映射错误。
如何解决 Gorm 1.25.7 的这个错误?
解决办法是将 gorm 回滚至 1.25.6 版本,在 go.mod 中修改即可。
Gorm 1.25.7 中 join 和 preload 同一个表时,错误发生在哪个源码位置?
错误发生在源码 preload.go 的第 124 行。
Gorm 1.25.7 这个错误有对应的 GitHub issue 吗?
有,参考 issue 编号为 6834。