在使用gorm-gen时,出现panic
生成语句:
g.GenerateModel("user", optVersionType := gen.FieldType("version", "optimisticlock.Version"))
生成的模型:
type User struct {
ID int64 `gorm:"column:id;primaryKey" json:"id"` // 主键
// 忽略其它字段
Version optimisticlock.Version `gorm:"column:version;not null" json:"version"` // 乐观锁
}
执行操作:
q.User.WithContext(ctx).Create(&model.User{ID: 123})
出现错误:
panic: reflect: call of reflect.Value.Field on slice Value [recovered]
panic: reflect: call of reflect.Value.Field on slice Value
panic({0x13f5d40, 0xc000438060})
C:/Users/NorthLan/.g/go/src/runtime/panic.go:838 +0x207
reflect.Value.Field({0x13d3160?, 0xc000438048?, 0x13b7da5?}, 0x0?)
C:/Users/NorthLan/.g/go/src/reflect/value.go:1220 +0xef
gorm.io/gorm/schema.(*Field).setupValuerAndSetter.func1({0xc000132c00?, 0x13?}, {0x13d3160?, 0xc000438048?, 0xf1be5d?})
C:/Users/NorthLan/go/pkg/mod/gorm.io/gorm@v1.23.6/schema/field.go:446 +0x65
gorm.io/plugin/optimisticlock.VersionCreateClause.ModifyStatement({0x20?}, 0xc00022d340)
C:/Users/NorthLan/go/pkg/mod/gorm.io/plugin/optimisticlock@v1.0.7/version.go:68 +0x4f
gorm.io/gorm.(*Statement).AddClause(0xc00022d340, {0x155ab08, 0xc000413680})
C:/Users/NorthLan/go/pkg/mod/gorm.io/gorm@v1.23.6/statement.go:257 +0x46
gorm.io/gorm/callbacks.Create.func1(0xc000432330)
C:/Users/NorthLan/go/pkg/mod/gorm.io/gorm@v1.23.6/callbacks/create.go:47 +0xf88
gorm.io/gorm.(*processor).Execute(0xc0001ffae0, 0xc00040fb28?)
C:/Users/NorthLan/go/pkg/mod/gorm.io/gorm@v1.23.6/callbacks.go:130 +0x433
gorm.io/gorm.(*DB).Create(0x144e1c0?, {0x13d3160?, 0xc000438048})
C:/Users/NorthLan/go/pkg/mod/gorm.io/gorm@v1.23.6/finisher_api.go:24 +0xa5
gorm.io/gen.(*DO).Save(0xc00040fc88, {0x13d3160, 0xc000438048})
C:/Users/NorthLan/go/pkg/mod/gorm.io/gen@v0.3.8/do.go:553 +0xba
看情况应该是 optimisticlock 插件通过反射寻找非零值的 Version
func (v VersionCreateClause) ModifyStatement(stmt *gorm.Statement) {
var value int64 = 1
if val, zero := v.Field.ValueOf(stmt.Context, stmt.ReflectValue); !zero {
if version, ok := val.(Version); ok {
value = version.Int64
}
}
stmt.SetColumn(v.Field.DBName, value)
}
摸一摸具体原因可能是:
因为gorm-gen的 Create 方法是传递的可变参数,stmt.ReflectValue 的 Kind是23(slice)而非25(struct)出现的错误。
// gorm-gen生成的Create方法
// u.DO.Create底层调用的还是 gorm.DB 的 Create 方法
func (u userDo) Create(values ...*model.User) error {
if len(values) == 0 {
return nil
}
return u.DO.Create(values)
}
特别地,如果使用 gorm.DB 的
Create就不会存在问题,例:db.Create(&user)特别地2,如果使用 gorm.DB 的
Create,但是传入slice,一样也会出现问题。例:db.Create(&[]model.User{user})
由此可得,可能得自己改一个 optimisticlock 插件
Comment From: tr1v3r
是准备自己实现这个需求吗?
Comment From: noahlann
是准备自己实现这个需求吗?
希望官方能够实现这个需求,但目前的情况看下来是插件的问题。
Comment From: github-actions[bot]
The issue has been automatically marked as stale as it missing playground pull request link, which is important to help others understand your issue effectively and make sure the issue hasn't been fixed on latest master, checkout https://github.com/go-gorm/playground for details. it will be closed in 30 days if no further activity occurs. if you are asking question, please use the Question template, most likely your question already answered https://github.com/go-gorm/gorm/issues or described in the document https://gorm.io ✨ Search Before Asking ✨
Comment From: a631807682
duplicate of https://github.com/go-gorm/optimisticlock/issues/9