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

Golang结构体中Slice无法追加新值,仅保留初始值问题

问题分析与解决方案

核心问题:遍历切片时操作的是值副本

你在遍历usersQuotes时使用了for _, userQuote := range usersQuotes,这里的userQuote是切片对应元素的值副本,并非原切片中结构体的引用。当执行userQuote.QuoteNumbers = append(userQuote.QuoteNumbers, quote)时,只是修改了这个临时副本的切片,原切片usersQuotes里的元素完全不受影响,所以后续看不到追加的quote。

次要问题:随机数种子重复初始化

把rand.Seed(time.Now().UnixNano())放在循环内部,会导致每次循环都重置随机数生成器。由于循环执行速度极快,time.Now().UnixNano()可能返回相同值,最终生成的随机数会大量重复,导致quote分配完全不均匀。

修复后的代码

type UserQuote struct {
    User         models.User
    QuoteNumbers []int
}

usersQuotes := make([]UserQuote, 0)

if len(usersThatBuySweepstakeNumbersBySweepstake) == 0 {
    // 补充空用户列表的处理逻辑
}

availableQuotes := GetAvailableSweepStakesNumbersNumbers(sweepStake.ID)
if availableQuotes == nil || len(availableQuotes) == 0 {
    c.AbortWithStatusJSON(400, gin.H{
        "message": "Não há mais números disponíveis para este sorteio",
    })
    return // 提前返回,避免后续无效代码执行
}

// 将随机数种子初始化移到循环外,仅执行一次
rand.Seed(time.Now().UnixNano())

for _, quote := range availableQuotes {
    randomIndex := rand.Intn(len(usersThatBuySweepstakeNumbersBySweepstake))
    selectedUser := usersThatBuySweepstakeNumbersBySweepstake[randomIndex]
    selectedUserIsInList := false

    // 通过索引访问原切片元素,直接修改原结构体
    for i := range usersQuotes {
        if usersQuotes[i].User.ID == selectedUser.ID {
            usersQuotes[i].QuoteNumbers = append(usersQuotes[i].QuoteNumbers, quote)
            selectedUserIsInList = true
            break // 找到匹配用户后立即跳出循环,减少不必要遍历
        }
    }

    if !selectedUserIsInList {
        usersQuotes = append(usersQuotes, UserQuote{
            User:         selectedUser,
            QuoteNumbers: []int{quote},
        })
    }
}

额外优化建议

如果用户数量较多,用切片遍历查找的效率会很低(时间复杂度O(n)),可以改用map存储用户与quote的关联,以用户ID为键,将查找操作的时间复杂度降到O(1):

// 用map替代切片,key为用户ID(根据实际类型调整键的类型)
userQuoteMap := make(map[uint]UserQuote)

// 分配quote的逻辑修改为:
for _, quote := range availableQuotes {
    randomIndex := rand.Intn(len(usersThatBuySweepstakeNumbersBySweepstake))
    selectedUser := usersThatBuySweepstakeNumbersBySweepstake[randomIndex]
    
    if uq, exists := userQuoteMap[selectedUser.ID]; exists {
        uq.QuoteNumbers = append(uq.QuoteNumbers, quote)
        userQuoteMap[selectedUser.ID] = uq
    } else {
        userQuoteMap[selectedUser.ID] = UserQuote{
            User:         selectedUser,
            QuoteNumbers: []int{quote},
        }
    }
}

// 若后续需要转回切片,遍历map即可:
var usersQuotes []UserQuote
for _, uq := range userQuoteMap {
    usersQuotes = append(usersQuotes, uq)
}

内容的提问来源于stack exchange,提问作者João Vitor Oliveira Corrêa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 22:12:48