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

使用DoAndReturn为Go接口参数赋值时遇nil问题求助

问题分析与解决

核心原因

你在DoAndReturn的闭包里直接给value赋值,这是值传递的问题——闭包里的value是原参数的副本,修改副本不会影响外部传入的变量。Go里的interface{}参数传递也是值拷贝,要修改原对象必须操作其底层指针。

另外,你的mock还存在类型不匹配问题:预期接收&models.Badge{}类型,但赋值的是[]*models.Thing,这会导致类型断言失败,即便解决了传递问题也无法正确赋值。

修正步骤

  1. 通过指针修改原对象:在闭包里用类型断言获取目标指针,修改指针指向的内容,这样外部传入的变量才会同步更新
  2. 保证类型匹配:mock的赋值类型要和预期的参数类型完全一致

修正后的测试代码(匹配*models.Badge类型)

s.mockRedisClient.EXPECT().GetStruct(gomock.Any(), cache.BadgesAll, gomock.AssignableToTypeOf(&models.Badge{})).DoAndReturn(func(ctx context.Context, key cache.Key, value any) (*time.Duration, error) {
    // 类型断言获取目标指针
    badgePtr, ok := value.(*models.Badge)
    if !ok {
        return nil, fmt.Errorf("invalid value type")
    }
    // 修改指针指向的内容,外部变量会同步更新
    *badgePtr = models.Badge{
        ID:   1,
        Name: "Test Badge",
        // 填充测试所需的其他字段
    }
    duration := time.Minute * 1
    return &duration, nil
})

如果实际需求是返回[]*models.Thing,则调整mock的参数预期:

s.mockRedisClient.EXPECT().GetStruct(gomock.Any(), cache.BadgesAll, gomock.AssignableToTypeOf(&[]*models.Thing{})).DoAndReturn(func(ctx context.Context, key cache.Key, value any) (*time.Duration, error) {
    thingsPtr, ok := value.(*[]*models.Thing)
    if !ok {
        return nil, fmt.Errorf("invalid value type")
    }
    *thingsPtr = []*models.Thing{{ID: 1}}
    duration := time.Minute * 1
    return &duration, nil
})

关键知识点

  • Go中所有参数都是值传递,包括interface{}——传递的是接口值的副本,要修改原对象必须操作其内部的指针
  • gomock的DoAndReturn闭包参数是原调用参数的副本,直接赋值不会影响外部变量
  • 必须保证mock的参数类型和被测代码传入的类型完全匹配,否则类型断言失败,赋值无效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 11:04:54