지금 고로 짠건 이렇게 짯거든요
코드 남보여 주는건 첨이라 너무 부끄러운데. 쨌든
구조체를 넘겨주면 필드 순회 하면서 바이트 배열로 바꿔주는 코드
func Decode(t interface{}) []byte { var BINARY []byte var Val = reflect.ValueOf(t) var Typ = reflect.TypeOf(t) var Knd = Val.Kind() _ = Typ if Knd == reflect.Ptr { if Val.IsNil() { return nil } Val = Val.Elem() Typ = Val.Type() Knd = Val.Kind() } // Handle value depend on itself's type switch Knd { // If type is Struct, we first trying to copy that // Because, without this process, if it is un-exported field, it will Panic. // After that, we will iterate whole fields. case reflect.Struct: var numField = Val.NumField() // copy // copiedOne := reflect.New(Val.Type()).Elem() copiedOne.Set(Val) ////////// for i := 0; i < numField; i++ { // field // var valField = copiedOne.Field(i) valField = reflect.NewAt(valField.Type(), unsafe.Pointer(valField.UnsafeAddr())).Elem() ///////// BINARY = append(BINARY, Decode(valField.Interface())...) } // NOTE: We simply tlqkfduddjwhwrkxsp // If you can sure that safe to use, you can modify to act like `(SIZE OF ELEMENT) * (BINARY OF ARRAY/SLICE)` case reflect.Array: for i := 0; i < Val.Len(); i++ { BINARY = append(BINARY, Decode(Val.Index(i).Interface())...) } // If type is Primitive type, especially Number-like type, // it will it self's size case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: BINARY = append(BINARY, uintToSlice(Val.Interface())...) } return BINARY }요건 빈 구조체에 바이너리 다시 덮어 씌우는거
func Encode(obj interface{}, bin []byte) error { size := Size(reflect.ValueOf(obj).Interface()) if size != len(bin) { log.Panic() return errors.New("Size of structure and size of given []byte is different") } index := 0 e := reflect.ValueOf(obj).Elem() fieldNum := e.NumField() for i := 0; i < fieldNum; i++ { v := e.Field(i) // Note: showing size of structure which measured by v.Type.Size() will NOT correct, due to byte alignment. // It works properly, in our situation, but if you really want to know actual size of that, use Size() at below. // fmt.Printf("Processing field %d/%d, Datatype: %s, ytes\n", i+1, fieldNum, v.Kind().String(), v.Type().Size()) switch v.Kind() { case reflect.Uint8: e.Field(i).SetUint(uint64(bin[index])) index++ case reflect.Uint16: e.Field(i).SetUint(uint64(binary.BigEndian.Uint16(bin[index : index+2]))) index += 2 case reflect.Uint32: e.Field(i).SetUint(uint64(binary.BigEndian.Uint32(bin[index : index+4]))) index += 4 case reflect.Uint64: e.Field(i).SetUint(uint64(binary.BigEndian.Uint64(bin[index : index+8]))) index += 8 case reflect.Array: reflect.Copy(e.Field(i), reflect.ValueOf(bin[index:index+e.Field(i).Len()])) index += e.Field(i).Len() case reflect.Struct: len := Size(v.Interface()) Encode(v.Addr().Interface(), bin[index:index+len]) index += len } } return nil }포인터 역참조 하는 코드도 어디 있었는데 못찾겠네용...
혹시 러스트는 이런게 쉽게? 세이프하게? 되나 해서 물어봤슴니다.
매크로로 타입세이프하게 할수있음
serde가 인터페이스 전부 제공하니까 Serializer만 바꾸면됨 json messagepack bincode같은 놈들은 이미 구현체 있고 커스텀 할려면 쟤만 구현하면끝
와우....한번 해보겠슴다 감사....