This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 47a284686 refactor(go): refine collection header bitmap (#2656)
47a284686 is described below

commit 47a2846867eafc5957fbcfd56365ddbe3212f926
Author: Zhong Junjie <[email protected]>
AuthorDate: Fri Sep 26 17:24:45 2025 +0800

    refactor(go): refine collection header bitmap (#2656)
    
    <!--
    **Thanks for contributing to Apache Fory™.**
    
    **If this is your first time opening a PR on fory, you can refer to
    
[CONTRIBUTING.md](https://github.com/apache/fory/blob/main/CONTRIBUTING.md).**
    
    Contribution Checklist
    
    - The **Apache Fory™** community has requirements on the naming of pr
    titles. You can also find instructions in
    [CONTRIBUTING.md](https://github.com/apache/fory/blob/main/CONTRIBUTING.md).
    
    - Apache Fory™ has a strong focus on performance. If the PR you submit
    will have an impact on performance, please benchmark it first and
    provide the benchmark result here.
    -->
    
    ## Why?
    
    <!-- Describe the purpose of this PR. -->
    
    Refine collection header bitmap to make it more understandable.
    
    
    ## What does this PR do?
    
    <!-- Describe the details of this PR. -->
    
    * Change the CollectionNotDeclElementType bit to
    CollectionIsDeclElementType, so now 0b100 represents declared type.
    * Fix several bugs inside writeSameType of collection serializer
    * Remove references tracking on string
    
    ## Related issues
    
    #2642
    
    <!--
    Is there any related issue? If this PR closes them you say say
    fix/closes:
    
    - #xxxx0
    - #xxxx1
    - Fixes #xxxx2
    -->
    
    ## Does this PR introduce any user-facing change?
    
    <!--
    If any user-facing interface changes, please [open an
    issue](https://github.com/apache/fory/issues/new/choose) describing the
    need to do so and update the document if necessary.
    
    Delete section if not applicable.
    -->
    
    - [x] Does this PR introduce any public API change? no
    - [x] Does this PR introduce any binary protocol compatibility change?
    no
    
    ## Benchmark
    
    <!--
    When the PR has an impact on performance (if you don't know whether the
    PR will have an impact on performance, you can submit the PR first, and
    if it will have impact on performance, the code reviewer will explain
    it), be sure to attach a benchmark data here.
    
    Delete section if not applicable.
    -->
---
 ci/run_ci.py              |  2 +-
 ci/run_ci.sh              | 10 ++---
 go/fory/fory.go           | 15 +++++++-
 go/fory/fory_test.go      | 28 --------------
 go/fory/reference.go      |  5 ---
 go/fory/reference_test.go |  2 +-
 go/fory/serializer.go     |  4 +-
 go/fory/set.go            | 16 ++++----
 go/fory/slice.go          | 94 +++++++++++++++++++++++++++++------------------
 go/fory/struct.go         | 53 +++++++++++++-------------
 go/fory/type.go           | 22 +++++++----
 go/fory/type_def.go       |  9 ++---
 12 files changed, 136 insertions(+), 124 deletions(-)

diff --git a/ci/run_ci.py b/ci/run_ci.py
index cdd8f7fbc..7818a9e60 100644
--- a/ci/run_ci.py
+++ b/ci/run_ci.py
@@ -293,7 +293,7 @@ def parse_args():
         if USE_PYTHON_GO:
             func()
         else:
-            # run_shell_script("go")
+            run_shell_script("go")
             pass
     elif command == "format":
         if USE_PYTHON_FORMAT:
diff --git a/ci/run_ci.sh b/ci/run_ci.sh
index bbc09feeb..e18e02728 100755
--- a/ci/run_ci.sh
+++ b/ci/run_ci.sh
@@ -356,11 +356,11 @@ case $1 in
     ;;
     go)
       echo "Executing fory go tests for go"
-      cd "$ROOT/go/fory"
-      go install ./cmd/fory
-      cd "$ROOT/go/fory/tests"
-      go generate
-      go test -v
+      # cd "$ROOT/go/fory"
+      # go install ./cmd/fory
+      # cd "$ROOT/go/fory/tests"
+      # go generate
+      # go test -v
       cd "$ROOT/go/fory"
       go test -v
       echo "Executing fory go tests succeeds"
diff --git a/go/fory/fory.go b/go/fory/fory.go
index abae4ef9b..3751452c8 100644
--- a/go/fory/fory.go
+++ b/go/fory/fory.go
@@ -374,7 +374,20 @@ func (f *Fory) writeValue(buffer *ByteBuffer, value 
reflect.Value, serializer Se
        if err != nil {
                return fmt.Errorf("cannot write typeinfo for value %v: %v", 
value, err)
        }
-       serializer = typeInfo.Serializer
+       // if compatible mode enable, use declared serializer to write value
+       if IsNamespacedType(TypeId(typeInfo.TypeID)) && f.compatible {
+               if declaredTypeDef, err := 
f.typeResolver.getTypeDef(typeInfo.Type, false); err != nil {
+                       return err
+               } else {
+                       ti, err := declaredTypeDef.buildTypeInfo()
+                       if err != nil {
+                               return err
+                       }
+                       serializer = ti.Serializer
+               }
+       } else {
+               serializer = typeInfo.Serializer
+       }
        // Serialize the actual value using the serializer
        return serializer.Write(f, buffer, value)
 }
diff --git a/go/fory/fory_test.go b/go/fory/fory_test.go
index cf1fdfb73..9c4981617 100644
--- a/go/fory/fory_test.go
+++ b/go/fory/fory_test.go
@@ -314,34 +314,6 @@ func TestSerializeStruct(t *testing.T) {
        }
 }
 
-func TestSerializeStringReference(t *testing.T) {
-       fory := NewFory(true)
-       strSlice := []string{"str1", "str1", "", "", "str2"}
-       strSlice = append(strSlice, strSlice[0])
-       serde(t, fory, strSlice)
-       type A struct {
-               F1 string
-               F2 string
-       }
-       require.Nil(t, fory.RegisterTagType("example.A", A{}))
-       serde(t, fory, A{})
-       serde(t, fory, A{F1: "str", F2: "str"})
-       var strData []byte
-       for i := 0; i < 1000; i++ {
-               strData = append(strData, 100)
-       }
-       x := string(strData)
-       serde(t, fory, &x)
-       strSlice2 := []string{x, x, x}
-       bytes, err := fory.Marshal(strSlice2)
-       require.Nil(t, err)
-       require.Less(t, len(bytes), 2*len(strData))
-       strSlice23 := []*string{&x, &x, &x}
-       bytes, err = fory.Marshal(strSlice23)
-       require.Nil(t, err)
-       require.Less(t, len(bytes), 2*len(strData))
-}
-
 func TestSerializeCircularReference(t *testing.T) {
        fory := NewFory(true)
        {
diff --git a/go/fory/reference.go b/go/fory/reference.go
index 389a01085..e0b89bc00 100644
--- a/go/fory/reference.go
+++ b/go/fory/reference.go
@@ -95,11 +95,6 @@ func (r *RefResolver) WriteRefOrNull(buffer *ByteBuffer, 
value reflect.Value) (r
        case reflect.Interface:
                value = value.Elem()
                return r.WriteRefOrNull(buffer, value)
-       case reflect.String:
-               isNil = false
-               str := unsafeGetBytes(value.Interface().(string))
-               value = reflect.ValueOf(str)
-               length = len(str)
        case reflect.Invalid:
                isNil = true
        case reflect.Struct:
diff --git a/go/fory/reference_test.go b/go/fory/reference_test.go
index 2cb333513..5f7329b3e 100644
--- a/go/fory/reference_test.go
+++ b/go/fory/reference_test.go
@@ -32,7 +32,7 @@ func TestReferenceResolver(t *testing.T) {
        values = append(values, commonMap()...)
        foo := newFoo()
        bar := Bar{}
-       values = append(values, "", "str", &foo, &bar)
+       values = append(values, &foo, &bar)
        for _, data := range values {
                refWritten, err := refResolver.WriteRefOrNull(buf, 
reflect.ValueOf(data))
                require.Nil(t, err)
diff --git a/go/fory/serializer.go b/go/fory/serializer.go
index 222083a2f..47afdb9b1 100644
--- a/go/fory/serializer.go
+++ b/go/fory/serializer.go
@@ -232,7 +232,7 @@ func (s stringSerializer) TypeId() TypeId {
 }
 
 func (s stringSerializer) NeedWriteRef() bool {
-       return true
+       return false
 }
 
 func (s stringSerializer) Write(f *Fory, buf *ByteBuffer, value reflect.Value) 
error {
@@ -468,7 +468,7 @@ func (s *ptrToValueSerializer) Read(f *Fory, buf 
*ByteBuffer, type_ reflect.Type
 }
 
 func writeBySerializer(f *Fory, buf *ByteBuffer, value reflect.Value, 
serializer Serializer, referencable bool) error {
-       if referencable {
+       if referencable && (serializer == nil || serializer.NeedWriteRef()) {
                return f.writeReferencableBySerializer(buf, value, serializer)
        } else {
                return f.writeNonReferencableBySerializer(buf, value, 
serializer)
diff --git a/go/fory/set.go b/go/fory/set.go
index d64982b6a..e18d8dd7a 100644
--- a/go/fory/set.go
+++ b/go/fory/set.go
@@ -55,7 +55,7 @@ func (s setSerializer) Write(f *Fory, buf *ByteBuffer, value 
reflect.Value) erro
        collectFlag, elemTypeInfo := s.writeHeader(f, buf, keys)
 
        // Check if all elements are of same type
-       if (collectFlag & CollectionNotSameType) == 0 {
+       if (collectFlag & CollectionIsSameType) != 0 {
                // Optimized path for same-type elements
                return s.writeSameType(f, buf, keys, elemTypeInfo, collectFlag)
        }
@@ -72,7 +72,7 @@ func (s setSerializer) writeHeader(f *Fory, buf *ByteBuffer, 
keys []reflect.Valu
        collectFlag := CollectionDefaultFlag
        var elemTypeInfo TypeInfo
        hasNull := false
-       hasDifferentType := false
+       hasSameType := true
 
        // Check elements to detect types
        // Initialize element type information from first non-null element
@@ -97,7 +97,7 @@ func (s setSerializer) writeHeader(f *Fory, buf *ByteBuffer, 
keys []reflect.Valu
                // Compare each element's type with the reference type
                currentTypeInfo, _ := f.typeResolver.getTypeInfo(key, true)
                if currentTypeInfo.TypeID != elemTypeInfo.TypeID {
-                       hasDifferentType = true
+                       hasSameType = false
                }
        }
 
@@ -105,8 +105,8 @@ func (s setSerializer) writeHeader(f *Fory, buf 
*ByteBuffer, keys []reflect.Valu
        if hasNull {
                collectFlag |= CollectionHasNull // Mark if collection contains 
null values
        }
-       if hasDifferentType {
-               collectFlag |= CollectionNotSameType // Mark if elements have 
different types
+       if hasSameType {
+               collectFlag |= CollectionIsSameType // Mark if elements have 
different types
        }
 
        // Enable reference tracking if configured
@@ -119,7 +119,7 @@ func (s setSerializer) writeHeader(f *Fory, buf 
*ByteBuffer, keys []reflect.Valu
        buf.WriteInt8(int8(collectFlag))      // Collection flags
 
        // Write element type ID if all elements have same type
-       if !hasDifferentType {
+       if hasSameType {
                buf.WriteVarInt32(elemTypeInfo.TypeID)
        }
 
@@ -206,7 +206,7 @@ func (s setSerializer) Read(f *Fory, buf *ByteBuffer, type_ 
reflect.Type, value
        var elemTypeInfo TypeInfo
 
        // If all elements are same type, read the shared type info
-       if (collectFlag & CollectionNotSameType) == 0 {
+       if (collectFlag & CollectionIsSameType) != 0 {
                typeID := buf.ReadVarInt32()
                elemTypeInfo, _ = f.typeResolver.getTypeInfoById(int16(typeID))
        }
@@ -219,7 +219,7 @@ func (s setSerializer) Read(f *Fory, buf *ByteBuffer, type_ 
reflect.Type, value
        f.refResolver.Reference(value)
 
        // Choose appropriate deserialization path based on type consistency
-       if (collectFlag & CollectionNotSameType) == 0 {
+       if (collectFlag & CollectionIsSameType) != 0 {
                return s.readSameType(f, buf, value, elemTypeInfo, collectFlag, 
length)
        }
        return s.readDifferentTypes(f, buf, value, length)
diff --git a/go/fory/slice.go b/go/fory/slice.go
index ef3810abd..3aae29fb3 100644
--- a/go/fory/slice.go
+++ b/go/fory/slice.go
@@ -23,15 +23,19 @@ import (
 )
 
 const (
-       CollectionDefaultFlag        = 0b0000
-       CollectionTrackingRef        = 0b0001
-       CollectionHasNull            = 0b0010
-       CollectionNotDeclElementType = 0b0100
-       CollectionNotSameType        = 0b1000
+       CollectionDefaultFlag       = 0b0000
+       CollectionTrackingRef       = 0b0001
+       CollectionHasNull           = 0b0010
+       CollectionIsDeclElementType = 0b0100
+       CollectionIsSameType        = 0b1000
+       CollectionDeclSameType      = CollectionIsSameType | 
CollectionIsDeclElementType
 )
 
+// sliceSerializer provides the dynamic slice implementation(e.g. 
[]interface{}) that inspects
+// element values at runtime
 type sliceSerializer struct {
-       elemInfo TypeInfo
+       elemInfo     TypeInfo
+       declaredType reflect.Type
 }
 
 func (s sliceSerializer) TypeId() TypeId {
@@ -55,7 +59,7 @@ func (s sliceSerializer) Write(f *Fory, buf *ByteBuffer, 
value reflect.Value) er
        collectFlag, elemTypeInfo := s.writeHeader(f, buf, value)
 
        // Choose serialization path based on type consistency
-       if (collectFlag & CollectionNotSameType) == 0 {
+       if (collectFlag & CollectionIsSameType) != 0 {
                return s.writeSameType(f, buf, value, elemTypeInfo, 
collectFlag) // Optimized path for same-type elements
        }
        return s.writeDifferentTypes(f, buf, value) // Fallback path for 
mixed-type elements
@@ -69,27 +73,38 @@ func (s sliceSerializer) writeHeader(f *Fory, buf 
*ByteBuffer, value reflect.Val
        collectFlag := CollectionDefaultFlag
        var elemTypeInfo TypeInfo
        hasNull := false
-       hasDifferentType := false
+       hasSameType := true
 
-       // Get type information for the first element
-       elemTypeInfo, _ = f.typeResolver.getTypeInfo(value, true)
-       collectFlag |= CollectionNotDeclElementType
+       // Seed elemTypeInfo from the first element so writeSameType can reuse 
it.
+       // Empty slices leave elemTypeInfo zero-value, which is also fine 
because
+       // writeSameType won't do anything in that case.
+       if value.Len() > 0 {
+               elemTypeInfo, _ = f.typeResolver.getTypeInfo(value.Index(0), 
true)
+       }
 
-       // Iterate through elements to check for nulls and type consistency
-       for i := 0; i < value.Len(); i++ {
-               elem := value.Index(i)
-               if elem.Kind() == reflect.Interface || elem.Kind() == 
reflect.Ptr {
-                       elem = elem.Elem()
-               }
-               if isNull(elem) {
-                       hasNull = true
-                       continue
-               }
+       if s.declaredType != nil {
+               collectFlag |= CollectionIsDeclElementType | 
CollectionIsSameType
+       } else {
+               // Iterate through elements to check for nulls and type 
consistency
+               var firstType reflect.Type
+               for i := 0; i < value.Len(); i++ {
+                       elem := value.Index(i)
+                       if elem.Kind() == reflect.Interface || elem.Kind() == 
reflect.Ptr {
+                               elem = elem.Elem()
+                       }
+                       if isNull(elem) {
+                               hasNull = true
+                               continue
+                       }
 
-               // Compare each element's type with the first element's type
-               currentTypeInfo, _ := f.typeResolver.getTypeInfo(elem, true)
-               if currentTypeInfo.TypeID != elemTypeInfo.TypeID {
-                       hasDifferentType = true
+                       // Compare each element's type with the first element's 
type
+                       if firstType == nil {
+                               firstType = elem.Type()
+                       } else {
+                               if firstType != elem.Type() {
+                                       hasSameType = false
+                               }
+                       }
                }
        }
 
@@ -97,12 +112,12 @@ func (s sliceSerializer) writeHeader(f *Fory, buf 
*ByteBuffer, value reflect.Val
        if hasNull {
                collectFlag |= CollectionHasNull // Mark if collection contains 
null values
        }
-       if hasDifferentType {
-               collectFlag |= CollectionNotSameType // Mark if elements have 
different types
+       if hasSameType {
+               collectFlag |= CollectionIsSameType // Mark if elements have 
same types
        }
 
-       // Enable reference tracking if configured
-       if f.refTracking {
+       // Enable reference tracking if configured and element type supports it
+       if f.refTracking && (elemTypeInfo.Serializer == nil || 
elemTypeInfo.Serializer.NeedWriteRef()) {
                collectFlag |= CollectionTrackingRef
        }
 
@@ -110,8 +125,8 @@ func (s sliceSerializer) writeHeader(f *Fory, buf 
*ByteBuffer, value reflect.Val
        buf.WriteVarUint32(uint32(value.Len())) // Collection size
        buf.WriteInt8(int8(collectFlag))        // Collection flags
 
-       // Write element type ID if all elements have same type
-       if !hasDifferentType {
+       // Write element type ID if all elements have same type and not using 
declared type
+       if hasSameType && (collectFlag&CollectionIsDeclElementType == 0) {
                buf.WriteVarInt32(elemTypeInfo.TypeID)
        }
 
@@ -124,7 +139,10 @@ func (s sliceSerializer) writeSameType(f *Fory, buf 
*ByteBuffer, value reflect.V
        trackRefs := (flag & CollectionTrackingRef) != 0 // Check if reference 
tracking is enabled
 
        for i := 0; i < value.Len(); i++ {
-               elem := value.Index(i).Elem()
+               elem := value.Index(i)
+               if elem.Kind() == reflect.Interface || elem.Kind() == 
reflect.Ptr {
+                       elem = elem.Elem()
+               }
                if isNull(elem) {
                        buf.WriteInt8(NullFlag) // Write null marker
                        continue
@@ -214,10 +232,14 @@ func (s sliceSerializer) Read(f *Fory, buf *ByteBuffer, 
type_ reflect.Type, valu
        collectFlag := buf.ReadInt8()
        var elemTypeInfo TypeInfo
        // Read element type information if all elements are same type
-       if (collectFlag & CollectionNotSameType) == 0 {
-               if (collectFlag & CollectionNotDeclElementType) != 0 {
+       if (collectFlag & CollectionIsSameType) != 0 {
+               if (collectFlag & CollectionIsDeclElementType) == 0 {
                        typeID := buf.ReadVarInt32()
-                       elemTypeInfo, _ = 
f.typeResolver.getTypeInfoById(int16(typeID))
+                       var err error
+                       elemTypeInfo, err = 
f.typeResolver.getTypeInfoById(int16(typeID))
+                       if err != nil {
+                               elemTypeInfo = s.elemInfo
+                       }
                } else {
                        elemTypeInfo = s.elemInfo
                }
@@ -241,7 +263,7 @@ func (s sliceSerializer) Read(f *Fory, buf *ByteBuffer, 
type_ reflect.Type, valu
        f.refResolver.Reference(value)
 
        // Choose appropriate deserialization path based on type consistency
-       if (collectFlag & CollectionNotSameType) == 0 {
+       if (collectFlag & CollectionIsSameType) != 0 {
                return s.readSameType(f, buf, value, elemTypeInfo, collectFlag)
        }
        return s.readDifferentTypes(f, buf, value)
diff --git a/go/fory/struct.go b/go/fory/struct.go
index 77e5b8056..9833c4b0b 100644
--- a/go/fory/struct.go
+++ b/go/fory/struct.go
@@ -44,6 +44,28 @@ func (s *structSerializer) NeedWriteRef() bool {
        return true
 }
 
+func (s *structSerializer) ensureFieldsInfo(f *Fory, fallbackType 
reflect.Type) error {
+       if s.fieldsInfo != nil {
+               return nil
+       }
+
+       var (
+               infos structFieldsInfo
+               err   error
+       )
+       if len(s.fieldDefs) == 0 {
+               infos, err = createStructFieldInfos(f, s.type_)
+       } else {
+               infos, err = createStructFieldInfosFromFieldDefs(f, 
s.fieldDefs, fallbackType)
+       }
+       if err != nil {
+               return err
+       }
+
+       s.fieldsInfo = infos
+       return nil
+}
+
 func (s *structSerializer) Write(f *Fory, buf *ByteBuffer, value 
reflect.Value) error {
        // If we have a codegen delegate, use it for optimal performance
        if s.codegenDelegate != nil {
@@ -51,13 +73,8 @@ func (s *structSerializer) Write(f *Fory, buf *ByteBuffer, 
value reflect.Value)
        }
 
        // Fall back to reflection-based serialization
-       // TODO support fields back and forward compatible. need to serialize 
fields name too.
-       if s.fieldsInfo == nil {
-               if fieldsInfo, err := createStructFieldInfos(f, s.type_); err 
!= nil {
-                       return err
-               } else {
-                       s.fieldsInfo = fieldsInfo
-               }
+       if err := s.ensureFieldsInfo(f, value.Type()); err != nil {
+               return err
        }
        if s.structHash == 0 {
                if hash, err := computeStructHash(s.fieldsInfo, 
f.typeResolver); err != nil {
@@ -99,22 +116,8 @@ func (s *structSerializer) Read(f *Fory, buf *ByteBuffer, 
type_ reflect.Type, va
                }
                value = value.Elem()
        }
-       if s.fieldsInfo == nil {
-               if len(s.fieldDefs) == 0 {
-                       // Normal case: create from reflection
-                       if infos, err := createStructFieldInfos(f, s.type_); 
err != nil {
-                               return err
-                       } else {
-                               s.fieldsInfo = infos
-                       }
-               } else {
-                       // Create from fieldDefs for forward/backward 
compatibility
-                       if infos, err := createStructFieldInfosFromFieldDefs(f, 
s.fieldDefs, type_); err != nil {
-                               return err
-                       } else {
-                               s.fieldsInfo = infos
-                       }
-               }
+       if err := s.ensureFieldsInfo(f, type_); err != nil {
+               return err
        }
        if s.structHash == 0 {
                if hash, err := computeStructHash(s.fieldsInfo, 
f.typeResolver); err != nil {
@@ -188,7 +191,7 @@ func createStructFieldInfos(f *Fory, type_ reflect.Type) 
(structFieldsInfo, erro
                                // so it has the potential and capability to 
use readSameTypes function.
                                if field.Type.Elem().Kind() != 
reflect.Interface {
                                        fieldSerializer = sliceSerializer{
-                                               
f.typeResolver.typesInfo[field.Type.Elem()],
+                                               elemInfo: 
f.typeResolver.typesInfo[field.Type.Elem()],
                                        }
                                }
                        }
@@ -280,7 +283,7 @@ func createStructFieldInfosFromFieldDefs(f *Fory, fieldDefs 
[]FieldDef, type_ re
                        fieldType = fieldTypeFromDef
                }
 
-               fieldSerializer, err := def.fieldType.getSerializer(f)
+               fieldSerializer, err := getFieldTypeSerializer(f, def.fieldType)
                if err != nil {
                        return nil, fmt.Errorf("failed to get serializer for 
field %s: %w", def.name, err)
                }
diff --git a/go/fory/type.go b/go/fory/type.go
index 7d0508af7..d754a258e 100644
--- a/go/fory/type.go
+++ b/go/fory/type.go
@@ -540,6 +540,10 @@ func (r *typeResolver) getSerializerByTypeTag(typeTag 
string) (Serializer, error
 
 func (r *typeResolver) getTypeInfo(value reflect.Value, create bool) 
(TypeInfo, error) {
        // First check if type info exists in cache
+       if value.Kind() == reflect.Interface {
+               // make sure the concrete value don't miss its real typeInfo
+               value = value.Elem()
+       }
        typeString := value.Type()
        if info, ok := r.typesInfo[typeString]; ok {
                if info.Serializer == nil {
@@ -563,9 +567,6 @@ func (r *typeResolver) getTypeInfo(value reflect.Value, 
create bool) (TypeInfo,
        if !create {
                fmt.Errorf("type %v not registered and create=false", 
value.Type())
        }
-       if value.Kind() == reflect.Interface {
-               value = value.Elem()
-       }
        type_ := value.Type()
        // Get package path and type name for registration
        var typeName string
@@ -804,7 +805,7 @@ func (r *typeResolver) writeSharedTypeMeta(buffer 
*ByteBuffer, typeInfo TypeInfo
        buffer.WriteVarUint32(newIndex)
        context.typeMap[typ] = newIndex
 
-       typeDef, err := r.getOrCreateTypeDef(typeInfo.Type)
+       typeDef, err := r.getTypeDef(typeInfo.Type, true)
        if err != nil {
                return err
        }
@@ -812,11 +813,15 @@ func (r *typeResolver) writeSharedTypeMeta(buffer 
*ByteBuffer, typeInfo TypeInfo
        return nil
 }
 
-func (r *typeResolver) getOrCreateTypeDef(typ reflect.Type) (*TypeDef, error) {
+func (r *typeResolver) getTypeDef(typ reflect.Type, create bool) (*TypeDef, 
error) {
        if existingTypeDef, exists := r.typeToTypeDef[typ]; exists {
                return existingTypeDef, nil
        }
 
+       if !create {
+               return nil, fmt.Errorf("TypeDef not found for type %s", typ)
+       }
+
        zero := reflect.Zero(typ)
        typeDef, err := buildTypeDef(r.fory, zero)
        if err != nil {
@@ -1234,8 +1239,11 @@ func (r *typeResolver) getTypeById(id int16) 
(reflect.Type, error) {
 }
 
 func (r *typeResolver) getTypeInfoById(id int16) (TypeInfo, error) {
-       typeInfo := r.typeIDToTypeInfo[int32(id)]
-       return typeInfo, nil
+       if typeInfo, exists := r.typeIDToTypeInfo[int32(id)]; exists {
+               return typeInfo, nil
+       } else {
+               return TypeInfo{}, fmt.Errorf("typeInfo of typeID %d not 
found", id)
+       }
 }
 
 func (r *typeResolver) writeMetaString(buffer *ByteBuffer, str string) error {
diff --git a/go/fory/type_def.go b/go/fory/type_def.go
index a7ab52f22..d0f9bf5c9 100644
--- a/go/fory/type_def.go
+++ b/go/fory/type_def.go
@@ -165,7 +165,7 @@ func buildFieldDefs(fory *Fory, value reflect.Value) 
([]FieldDef, error) {
                serializers := make([]Serializer, len(fieldDefs))
                fieldNames := make([]string, len(fieldDefs))
                for i, fieldDef := range fieldDefs {
-                       serializer, err := 
fieldDef.fieldType.getSerializer(fory)
+                       serializer, err := getFieldTypeSerializer(fory, 
fieldDef.fieldType)
                        if err != nil {
                                // If we can't get serializer, use nil (will be 
handled by sortFields)
                                serializers[i] = nil
@@ -199,7 +199,6 @@ func buildFieldDefs(fory *Fory, value reflect.Value) 
([]FieldDef, error) {
 type FieldType interface {
        TypeId() TypeId
        write(*ByteBuffer)
-       getSerializer(*Fory) (Serializer, error)
        getTypeInfo(*Fory) (TypeInfo, error) // some serializer need typeinfo 
as well
 }
 
@@ -213,8 +212,8 @@ func (b *BaseFieldType) write(buffer *ByteBuffer) {
        buffer.WriteVarUint32Small7(uint32(b.typeId))
 }
 
-func (b *BaseFieldType) getSerializer(fory *Fory) (Serializer, error) {
-       typeInfo, err := b.getTypeInfo(fory)
+func getFieldTypeSerializer(fory *Fory, ft FieldType) (Serializer, error) {
+       typeInfo, err := ft.getTypeInfo(fory)
        if err != nil {
                return nil, err
        }
@@ -284,7 +283,7 @@ func (c *CollectionFieldType) getTypeInfo(f *Fory) 
(TypeInfo, error) {
        if err != nil {
                return TypeInfo{}, err
        }
-       sliceSerializer := &sliceSerializer{elemInfo: elemInfo}
+       sliceSerializer := &sliceSerializer{elemInfo: elemInfo, declaredType: 
elemInfo.Type}
        return TypeInfo{Type: collectionType, Serializer: sliceSerializer}, nil
 }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to