众所周知,浮点数是很调皮的
都谁在说,喜欢技术八卦的你,不可以错过
浮点计算引发的血案
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的接口怎这么费眼睛呢?
网友评论