一切都源于我开发中发现的一个bug,简单描述就是 先insert 了一条数据,然后开启了一个协程,直接进行查询刚才插入的数据,竟然没查到。
代码如下
func Test(t *testing.T) {
record := &model.ContentCoursePracticeRecord{
Cid: 0,
Uid: 1,
Complete: 1,
Type: 2,
Duration: 100,
Ctime: time.Now(),
Uptime: time.Now(),
}
err := dao.ContentCoursePracticeRecordDao.Create(record)
assert.Equal(t, err, nil)
go func() {
// 查询0元购活动
var (
duration int
)
db, err := utils.GetDB()
if err != nil {
assert.Equal(t, err, nil)
}
if ret := db.Model(&model.ContentCoursePracticeRecord{}).
Where("isdel = 0 and uid = ?", 1).
Where("ctime >= ?", time.Now().Format("2006-01-02")).
Select("sum(duration) as duration").
Find(&duration); ret.Error != nil {
// 此处报错 ,说明没有数据
//sql: Scan error on column index 0, name "duration": converting NULL to int is unsupported
assert.Equal(t, err, nil)
}
}()
}
他不是一个必现的问题,我也没有成功复现出来 后来把查询从写成挪出去就没有问题了,但是也没有想明白问题?望各位大佬指点!
有疑问加站长微信联系(非本文作者))

查询单个列,使用Pluck方法
查询多个列,使用Select或者Scan
Find方法通常是Struct或者Slice
阅读一下Gorm的查询及高级查询篇
我关注不是报错本身,是为什么会查询不到数据,明明已经插入了。不使用协程直接查询,就在没有问题,是协程那些特性导致的问题?
协程是在主线程下的一个子协程,主线程结束了,子协程也就结束了(此时,子协程不一定被执行了)
在调用协程后面添加一个等待的代码即可。例如time.Sleep(1 *time.Second)
还是协程调度的问题,如果插入操作花费的时间比较长,而子协程在此期间开始执行,那么子协程就有可能在新插入的数据还没有被写入到数据库时进行查询操作,从而导致查询不到数据的情况。
gorm create 方法不会等待结束就继续向下执行吗,不应该吧,后面我打印log 都可以拿到自增id了
gorm create 方法不会等待结束就继续向下执行吗,不应该吧,后面我打印log 都可以拿到自增id了
好烦,调试方向都没有了
好好看看那个时间大😂