美文网首页Golang全靠你了
你的mongoDB也要和decimal组CP

你的mongoDB也要和decimal组CP

作者: Godan | 来源:发表于2020-09-18 00:23 被阅读0次

    众所周知,浮点数是很调皮的

    都谁在说,喜欢技术八卦的你,不可以错过
    浮点计算引发的血案
    Go如何精确计算小数-Decimal研究-Tidb MyDecimal问题

    mongodb/mongo-go-driver中的bson.Decimal128只顾及自家存储的一亩三分地,看起来干干巴巴、麻麻赖赖…… 大家先不着急盘它,据说有个俊俏的 github.com/shopspring/decimal,咱们可以说个媒。

    // 我希望mongo中,读取数据时decimal类型直接解析到decimal.Decimal中
    // 写入时,又直接把decimal.Decimal放入到mongo的decimal类型中
    type Model struct {
      // 这个VIP积分非常重要,弄错公司就玩完啦~
      // 只有他才配的上 decimal.Decimal (狗头
      VIPScore decimal.Decimal `bson:"vip_score"`
    }
    

    这回文档有点不好使啦,只能用google到处搜,到处搜

    package mongo
    
    import (
        "fmt"
        "reflect"
    
        "github.com/shopspring/decimal"
        "go.mongodb.org/mongo-driver/bson/bsoncodec"
        "go.mongodb.org/mongo-driver/bson/bsonrw"
        "go.mongodb.org/mongo-driver/bson/bsontype"
        "go.mongodb.org/mongo-driver/bson/primitive"
    )
    
    type Decimal decimal.Decimal
    
    func (d Decimal) DecodeValue(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
        decimalType := reflect.TypeOf(decimal.Decimal{})
        if !val.IsValid() || !val.CanSet() || val.Type() != decimalType {
            return bsoncodec.ValueDecoderError{
                Name:     "decimalDecodeValue",
                Types:    []reflect.Type{decimalType},
                Received: val,
            }
        }
    
        var value decimal.Decimal
        switch vr.Type() {
        case bsontype.Decimal128:
            dec, err := vr.ReadDecimal128()
            if err != nil {
                return err
            }
            value, err = decimal.NewFromString(dec.String())
            if err != nil {
                return err
            }
        default:
            return fmt.Errorf("received invalid BSON type to decode into decimal.Decimal: %s", vr.Type())
        }
    
        val.Set(reflect.ValueOf(value))
        return nil
    }
    
    func (d Decimal) EncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
        decimalType := reflect.TypeOf(decimal.Decimal{})
        if !val.IsValid() || val.Type() != decimalType {
            return bsoncodec.ValueEncoderError{
                Name:     "decimalEncodeValue",
                Types:    []reflect.Type{decimalType},
                Received: val,
            }
        }
    
        dec := val.Interface().(decimal.Decimal)
        dec128, err := primitive.ParseDecimal128(dec.String())
        if err != nil {
            return err
        }
    
        return vw.WriteDecimal128(dec128)
    }
    

    然后呢,需要到ClientOptions注册自定义编码解码

         cli, err := mongo.NewClient(options.Client().ApplyURI("这是个mongoURI连接地址").
                SetRegistry(bson.NewRegistryBuilder().
                    RegisterDecoder(reflect.TypeOf(decimal.Decimal{}), Decimal{}).
                    RegisterEncoder(reflect.TypeOf(decimal.Decimal{}), Decimal{}).
                    Build())
        if err != nil {
            log.Fatal().Err(err).Msg("连接到mongo")
        }
    

    大概就是这样。

    另外,我想帮一个朋友问问mongo的接口怎这么费眼睛呢?

    相关文章

      网友评论

        本文标题:你的mongoDB也要和decimal组CP

        本文链接:https://www.haomeiwen.com/subject/isqdyktx.html