为Go Mongo Official驱动程序创建自定义编码器时的最佳做法

I was just wondering what the best practices were in regards to handling the creation of custom encoder for the support Go Mongo drivers. The following is my current implementation of a custom handler for Binary, OID and Date data that is retrieved from the database and encoded to JSON.


var CustomRegistry = createCustomRegistry().Build()
var tBinary = reflect.TypeOf(primitive.Binary{})
var tOID = reflect.TypeOf(primitive.ObjectID{})
var tDateTime = reflect.TypeOf(primitive.DateTime(0))

func createCustomRegistry() *bsoncodec.RegistryBuilder {
    var primitiveCodecs bson.PrimitiveCodecs
    rb := bsoncodec.NewRegistryBuilder()
    bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb)
    bsoncodec.DefaultValueDecoders{}.RegisterDefaultDecoders(rb)
    rb.RegisterEncoder(tBinary, bsoncodec.ValueEncoderFunc(binaryEncodeCustomValue))
    rb.RegisterEncoder(tOID, bsoncodec.ValueEncoderFunc(objectIDEncodeValue))
    rb.RegisterEncoder(tDateTime, bsoncodec.ValueEncoderFunc(dateTimeEncodeValue))
    primitiveCodecs.RegisterPrimitiveCodecs(rb)
    return rb
}

func binaryEncodeCustomValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
    if !val.IsValid() || val.Type() != tBinary {
        return bsoncodec.ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: val}
    }

    in := val.Interface().(primitive.Binary)
    out := make([]byte, base64.StdEncoding.EncodedLen(len(in.Data)))
    base64.StdEncoding.Encode(out, in.Data)
    s, err := util.BinaryToCSUUID(in.Data)
    if err != nil {
        return bsoncodec.ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: val}
    }

    return vw.WriteString(s)
}

func objectIDEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
    if !val.IsValid() || val.Type() != tOID {
        return bsoncodec.ValueEncoderError{Name: "ObjectIDEncodeValue", Types: []reflect.Type{tOID}, Received: val}
    }
    s := val.Interface().(primitive.ObjectID).Hex()
    return vw.WriteString(s)
}

func dateTimeEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
    const jdateFormat = "2006-01-02T15:04:05.999Z"
    if !val.IsValid() || val.Type() != tDateTime {
        return bsoncodec.ValueEncoderError{Name: "DateTimeEncodeValue", Types: []reflect.Type{tDateTime}, Received: val}
    }

    ints := val.Int()
    t := time.Unix(0, ints*1000000)

    return vw.WriteString(t.Format(jdateFormat))
}

I call the above code using the following function:

data, writeErr := bson.MarshalExtJSONWithRegistry(CustomRegistry, result, false, false)

I did not find much documentation on how this should be handled. Is there a better method to do this?