You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GORM查询updated_at条件异常:预期空结果却返回数据的解决

Fixing GORM Query Result Overwritten by Goroutine Operations

Hey, let's break down what's going on here and get this sorted out:

The Root Cause

The core issue here is that you're reusing the same onedays slice variable across multiple goroutines, and GORM's Find method overwrites the contents of the slice you pass to it. When you run your targeted query with the updated_at condition in the main goroutine, the goroutine running the simpler user_id-only query is writing its results to the same onedays slice afterward (or concurrently), replacing the expected empty result with those two records.

It's not a problem with GORM's query builder itself—GORM's *gorm.DB instances are safe for concurrent use because each chain (like Where().Find()) creates a new, isolated query object. The conflict is purely from sharing the result slice.

Solutions

1. Use Separate Slice Variables for Each Query

The cleanest fix is to create a dedicated slice for each query, so their results never overlap. This eliminates any cross-goroutine interference entirely:

// Main goroutine: use a local slice for your targeted query
var targetedResults []Oneday
if err := rDB.Where("user_id = ? AND updated_at > ?", userID, date).Find(&targetedResults).Error; err != nil {
    // Handle error here (log, return, etc.)
}
// Work with targetedResults—this won't be touched by the goroutine

// Goroutine: use its own independent slice
go func() {
    var goroutineResults []Oneday
    if err := rDB.Where("user_id = ?", userID).Find(&goroutineResults).Error; err != nil {
        // Handle goroutine-specific error
    }
    // Use goroutineResults without affecting the main query's data
}()

2. Use Synchronization if You Must Share Data

If your business logic absolutely requires sharing the same slice between goroutines, you need to use a mutex to ensure only one operation writes to the slice at a time. This will serialize the queries, so they don't overwrite each other:

import "sync"

// Define a mutex alongside your shared slice
var (
    sharedOnedays []Oneday
    sliceMutex    sync.Mutex
)

// Main goroutine query with lock
sliceMutex.Lock()
defer sliceMutex.Unlock()
if err := rDB.Where("user_id = ? AND updated_at > ?", userID, date).Find(&sharedOnedays).Error; err != nil {
    // Handle error
}

// Goroutine query with lock
go func() {
    sliceMutex.Lock()
    defer sliceMutex.Unlock()
    if err := rDB.Where("user_id = ?", userID).Find(&sharedOnedays).Error; err != nil {
        // Handle error
    }
}()

Note: This approach will make the queries run one after another, which could impact performance. Only use this if sharing the slice is unavoidable.

3. Verify the Base Query Works

Before wrapping up, double-check that your original targeted query works in isolation to rule out any other issues:

var testResults []Oneday
if err := rDB.Where("user_id = ? AND updated_at > ?", 44, "2018-01-04 23:18:00").Find(&testResults).Error; err != nil {
    log.Fatal(err)
}
fmt.Printf("Test result count: %d\n", len(testResults)) // Should output 0, matching your direct SQL result

内容的提问来源于stack exchange,提问作者rluisr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:07:44