I am encoding a rather complex structure using a very complicated protocol that's a mix of ASN and a variant of XDR and other encodings.
I based the implementation on xdr encoder available on github. The code is reflection based and it works, but I don't like how I implemented target type switch:
st := ve.Type().String()
switch st {
case "time.Time":
I think the following approach might be better, but I could not get it to work properly:
switch ve.(type) {
case time.Time:
The reason it does not work is that ve is of the same reflection type and not the target type.
The following function provides full context of the code:
func (enc *encoderState) encode(v reflect.Value) {
ve := enc.indirect(v)
st := ve.Type().String()
switch st {
case "time.Time":
log.Println("Handling time.Time")
t, ok := ve.Interface().(time.Time)
if !ok {
enc.err = errors.New("Failed to type assert to time.Time")
return
}
enc.encodeTime(t)
return
case "[]uint8":
log.Println("Handling []uint8")
enc.writeOctetString(ve.Bytes())
return
default:
log.Printf("Handling type: %v by kind: %v\n", st, ve.Kind())
}
// Handle native Go types.
switch ve.Kind() {
case reflect.Uint8: // , reflect.Int8
enc.writeUint8(uint8(v.Uint()))
return
case reflect.Uint16: // , reflect.Int16
enc.writeUint16(uint16(v.Uint()))
return
case reflect.Bool:
enc.writeBool(ve.Bool())
return
case reflect.Struct:
enc.encodeStruct(ve)
return
case reflect.Interface:
enc.encodeInterface(ve)
return
}
// The only unhandled types left are unsupported. At the time of this
// writing the only remaining unsupported types that exist are
// reflect.Uintptr and reflect.UnsafePointer.
enc.err = errors.New(fmt.Sprintf("unsupported Go type '%s'", ve.Kind().String()))
}
If you know of a better example that can switch by type and kind better, please, let me know.
Thank you
Aucun commentaire:
Enregistrer un commentaire