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

github.com/shopspring/decimal:NewFromString与NewFromFloat64生成值不一致导致gomock断言失败问题问询

为什么decimal.NewFromString和NewFromFloat64生成的实例在Gomock断言中不匹配?

这是个很典型的浮点数精度+库内部表示导致的问题,我来给你拆解清楚:

核心原因

  1. 浮点数的天生精度缺陷
    float64类型在二进制存储时,无法精确表示所有十进制小数——哪怕是看起来像整数的数值,某些场景下也会存在近似存储的情况。decimal.NewFromFloat64是基于浮点数的近似二进制值转换生成decimal实例,而decimal.NewFromString是直接解析十进制字符串的精确数值,两者的内部存储(比如big.Int的系数、指数值)可能会出现细微差异。

  2. Gomock的默认匹配逻辑
    Gomock默认用reflect.DeepEqual来比较参数是否相等。对于decimal类型来说,它的内部结构包含*big.Int指针,即使两个实例的数值看起来一样,只要指针指向的不是同一个big.Int对象,或者内部系数/指数有差异,reflect.DeepEqual就会判定它们不相等。而当你在测试和业务代码中都用NewFromString生成实例时,两者的精确内部表示完全一致,自然能通过断言。

解决办法

针对这个问题,你有几个实用的处理方式:

  • 统一生成方式:测试中完全复刻业务代码的逻辑,用decimal.NewFromString创建预期参数,从根源避免浮点数转换带来的精度问题。
  • 自定义匹配器:如果必须用浮点数生成测试参数,可以借助Gomock的自定义匹配器,用decimal自身的Equal方法来判断数值是否相等(而不是依赖默认的反射比较),示例代码如下:
    value := decimal.NewFromFloat64(1000)
    cfg.cdi.EXPECT().CreateBuyEvent(ctx, gomock.Matches(func(v decimal.Decimal) bool {
        return v.Equal(value)
    })).Return(nil)
    
  • 避免浮点数传入:在涉及精确数值的场景中,尽量用字符串或整数来初始化decimal,从源头规避浮点数精度风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 18:53:08