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 bd0bd5b09 feat(go): Add slice and map support to fory-go codegen 
serialization (#2638)
bd0bd5b09 is described below

commit bd0bd5b090c8cc27aceaf76b72fbae2a3df4e104
Author: thisingl <[email protected]>
AuthorDate: Tue Sep 23 12:03:29 2025 +0800

    feat(go): Add slice and map support to fory-go codegen serialization (#2638)
    
    <!--
    **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.
    -->
    
    
    
    ## What does this PR do?
    
    - Extends the ahead-of-time code generation to support serialization and
    deserialization of slice types.
    
    - Implements serialization and deserialization logic for map types.
    
    - Enhances the generated Write and Read methods to cover these
    collection types.
    
    
    
    ## Related issues
    - #2227
    <!--
    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.
    -->
    
    - [ ] Does this PR introduce any public API change?
    - [ ] Does this PR introduce any binary protocol compatibility change?
    
    ## 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.
    -->
---
 go/README.md                          |  24 +-
 go/fory/codegen/decoder.go            | 485 +++++++++++++++++++++++++++++++++-
 go/fory/codegen/encoder.go            | 453 ++++++++++++++++++++++++++++++-
 go/fory/codegen/guard.go              |  13 +-
 go/fory/codegen/utils.go              | 220 +++++++++++----
 go/fory/struct.go                     |  36 ++-
 go/fory/tests/generator_test.go       | 162 +++++++++++-
 go/fory/tests/generator_xlang_test.go | 291 ++++++++++++++++++++
 go/fory/tests/structs.go              |  35 ++-
 go/fory/type.go                       |  64 +++--
 10 files changed, 1680 insertions(+), 103 deletions(-)

diff --git a/go/README.md b/go/README.md
index 7dd44f912..bd0105ae4 100644
--- a/go/README.md
+++ b/go/README.md
@@ -2,7 +2,27 @@
 
 Fory is a blazingly fast multi-language serialization framework powered by 
just-in-time compilation and zero-copy.
 
-Currently, Fory Go is implemented using reflection. We have also implemented a 
static code generator to generate serializer code ahead of time to speed up 
serialization.
+Fory Go provides two serialization paths: a high-performance code generation 
path and a reflection-based path. The code generation path is recommended for 
production use as it offers better performance and broader type support.
+
+## Supported Types
+
+Fory Go supports the following types for both reflection-based serialization 
and code generation:
+
+### Basic Data Types
+
+- `bool`
+- `int8`, `int16`, `int32`, `int64`, `int`
+- `uint8` (byte)
+- `float32`, `float64`
+- `string`
+
+### Collection Types
+
+- `[]bool`, `[]int16`, `[]int32`, `[]int64`
+- `[]float32`, `[]float64`
+- `[]string`
+- `[]interface{}` (dynamic slice)
+- `map[string]string`, `map[int]int`, `map[string]int`
 
 ## Fory Go Codegen (optional)
 
@@ -27,7 +47,7 @@ The generator binary is `fory`.
 go install github.com/apache/fory/go/fory/cmd/fory@latest
 ```
 
-- Go 1.13+
+- Go 1.13+:
 
 ```bash
 # Inside a module-enabled environment
diff --git a/go/fory/codegen/decoder.go b/go/fory/codegen/decoder.go
index 345f283c6..4cf048485 100644
--- a/go/fory/codegen/decoder.go
+++ b/go/fory/codegen/decoder.go
@@ -21,6 +21,8 @@ import (
        "bytes"
        "fmt"
        "go/types"
+
+       "github.com/apache/fory/go/fory"
 )
 
 // generateReadTyped generates the strongly-typed Read method
@@ -110,15 +112,24 @@ func generateFieldReadTyped(buf *bytes.Buffer, field 
*FieldInfo) error {
        if basic, ok := field.Type.Underlying().(*types.Basic); ok {
                switch basic.Kind() {
                case types.Bool:
+                       fmt.Fprintf(buf, "\tif flag := buf.ReadInt8(); flag != 
-1 {\n")
+                       fmt.Fprintf(buf, "\t\treturn fmt.Errorf(\"expected 
NotNullValueFlag for field %s, got %%d\", flag)\n", field.GoName)
+                       fmt.Fprintf(buf, "\t}\n")
                        fmt.Fprintf(buf, "\t%s = buf.ReadBool()\n", fieldAccess)
                case types.Int8:
                        fmt.Fprintf(buf, "\t%s = buf.ReadInt8()\n", fieldAccess)
                case types.Int16:
                        fmt.Fprintf(buf, "\t%s = buf.ReadInt16()\n", 
fieldAccess)
                case types.Int32:
-                       fmt.Fprintf(buf, "\t%s = buf.ReadInt32()\n", 
fieldAccess)
+                       fmt.Fprintf(buf, "\tif flag := buf.ReadInt8(); flag != 
-1 {\n")
+                       fmt.Fprintf(buf, "\t\treturn fmt.Errorf(\"expected 
NotNullValueFlag for field %s, got %%d\", flag)\n", field.GoName)
+                       fmt.Fprintf(buf, "\t}\n")
+                       fmt.Fprintf(buf, "\t%s = buf.ReadVarint32()\n", 
fieldAccess)
                case types.Int, types.Int64:
-                       fmt.Fprintf(buf, "\t%s = buf.ReadInt64()\n", 
fieldAccess)
+                       fmt.Fprintf(buf, "\tif flag := buf.ReadInt8(); flag != 
-1 {\n")
+                       fmt.Fprintf(buf, "\t\treturn fmt.Errorf(\"expected 
NotNullValueFlag for field %s, got %%d\", flag)\n", field.GoName)
+                       fmt.Fprintf(buf, "\t}\n")
+                       fmt.Fprintf(buf, "\t%s = buf.ReadVarint64()\n", 
fieldAccess)
                case types.Uint8:
                        fmt.Fprintf(buf, "\t%s = buf.ReadByte_()\n", 
fieldAccess)
                case types.Uint16:
@@ -130,8 +141,14 @@ func generateFieldReadTyped(buf *bytes.Buffer, field 
*FieldInfo) error {
                case types.Float32:
                        fmt.Fprintf(buf, "\t%s = buf.ReadFloat32()\n", 
fieldAccess)
                case types.Float64:
+                       fmt.Fprintf(buf, "\tif flag := buf.ReadInt8(); flag != 
-1 {\n")
+                       fmt.Fprintf(buf, "\t\treturn fmt.Errorf(\"expected 
NotNullValueFlag for field %s, got %%d\", flag)\n", field.GoName)
+                       fmt.Fprintf(buf, "\t}\n")
                        fmt.Fprintf(buf, "\t%s = buf.ReadFloat64()\n", 
fieldAccess)
                case types.String:
+                       fmt.Fprintf(buf, "\tif flag := buf.ReadInt8(); flag != 
0 {\n")
+                       fmt.Fprintf(buf, "\t\treturn fmt.Errorf(\"expected 
RefValueFlag for field %s, got %%d\", flag)\n", field.GoName)
+                       fmt.Fprintf(buf, "\t}\n")
                        fmt.Fprintf(buf, "\t%s = fory.ReadString(buf)\n", 
fieldAccess)
                default:
                        fmt.Fprintf(buf, "\t// TODO: unsupported basic type 
%s\n", basic.String())
@@ -139,6 +156,57 @@ func generateFieldReadTyped(buf *bytes.Buffer, field 
*FieldInfo) error {
                return nil
        }
 
+       // Handle slice types
+       if slice, ok := field.Type.(*types.Slice); ok {
+               elemType := slice.Elem()
+               // Check if element type is interface{} (dynamic type)
+               if iface, ok := elemType.(*types.Interface); ok && 
iface.Empty() {
+                       // For []interface{}, we need to manually implement the 
deserialization
+                       // to match our custom encoding
+                       fmt.Fprintf(buf, "\t// Dynamic slice []interface{} 
handling - manual deserialization\n")
+                       fmt.Fprintf(buf, "\tif flag := buf.ReadInt8(); flag == 
-3 {\n")
+                       fmt.Fprintf(buf, "\t\t%s = nil // null slice\n", 
fieldAccess)
+                       fmt.Fprintf(buf, "\t} else if flag == 0 {\n")
+                       fmt.Fprintf(buf, "\t\t// Read slice length\n")
+                       fmt.Fprintf(buf, "\t\tsliceLen := 
buf.ReadVarUint32()\n")
+                       fmt.Fprintf(buf, "\t\t// Read collection flags (ignore 
for now)\n")
+                       fmt.Fprintf(buf, "\t\t_ = buf.ReadInt8()\n")
+                       fmt.Fprintf(buf, "\t\t// Create slice with proper 
capacity\n")
+                       fmt.Fprintf(buf, "\t\t%s = make([]interface{}, 
sliceLen)\n", fieldAccess)
+                       fmt.Fprintf(buf, "\t\t// Read each element using 
ReadReferencable\n")
+                       fmt.Fprintf(buf, "\t\tfor i := range %s {\n", 
fieldAccess)
+                       fmt.Fprintf(buf, "\t\t\tf.ReadReferencable(buf, 
reflect.ValueOf(&%s[i]).Elem())\n", fieldAccess)
+                       fmt.Fprintf(buf, "\t\t}\n")
+                       fmt.Fprintf(buf, "\t} else {\n")
+                       fmt.Fprintf(buf, "\t\treturn fmt.Errorf(\"expected 
RefValueFlag or NullFlag for dynamic slice field %s, got %%d\", flag)\n", 
field.GoName)
+                       fmt.Fprintf(buf, "\t}\n")
+                       return nil
+               }
+               // For static element types, use optimized inline generation
+               if err := generateSliceReadInline(buf, slice, fieldAccess); err 
!= nil {
+                       return err
+               }
+               return nil
+       }
+
+       // Handle map types
+       if mapType, ok := field.Type.(*types.Map); ok {
+               // For map types, we'll use manual deserialization following 
the chunk-based format
+               if err := generateMapReadInline(buf, mapType, fieldAccess); err 
!= nil {
+                       return err
+               }
+               return nil
+       }
+
+       // Handle interface types
+       if iface, ok := field.Type.(*types.Interface); ok {
+               if iface.Empty() {
+                       // For interface{}, use ReadReferencable for dynamic 
type handling
+                       fmt.Fprintf(buf, "\tf.ReadReferencable(buf, 
reflect.ValueOf(&%s).Elem())\n", fieldAccess)
+                       return nil
+               }
+       }
+
        // Handle struct types
        if _, ok := field.Type.Underlying().(*types.Struct); ok {
                fmt.Fprintf(buf, "\tf.ReadReferencable(buf, 
reflect.ValueOf(&%s).Elem())\n", fieldAccess)
@@ -148,3 +216,416 @@ func generateFieldReadTyped(buf *bytes.Buffer, field 
*FieldInfo) error {
        fmt.Fprintf(buf, "\t// TODO: unsupported type %s\n", 
field.Type.String())
        return nil
 }
+
+// Note: generateSliceRead is no longer used since we use 
WriteReferencable/ReadReferencable for slice fields
+// generateSliceRead generates code to deserialize a slice according to the 
list format
+func generateSliceRead(buf *bytes.Buffer, sliceType *types.Slice, fieldAccess 
string) error {
+       elemType := sliceType.Elem()
+
+       // Use block scope to avoid variable redeclaration across multiple 
slice fields
+       fmt.Fprintf(buf, "\t// Read slice %s\n", fieldAccess)
+       fmt.Fprintf(buf, "\t{\n")
+       fmt.Fprintf(buf, "\t\tsliceLen := int(buf.ReadVarUint32())\n")
+       fmt.Fprintf(buf, "\t\tif sliceLen == 0 {\n")
+       fmt.Fprintf(buf, "\t\t\t// Empty slice - matching reflection behavior 
where nil and empty are treated the same\n")
+       fmt.Fprintf(buf, "\t\t\t%s = nil\n", fieldAccess)
+       fmt.Fprintf(buf, "\t\t} else {\n")
+
+       // Read collection flags for non-empty slice
+       fmt.Fprintf(buf, "\t\t\t// Read collection flags\n")
+       fmt.Fprintf(buf, "\t\t\tcollectFlag := buf.ReadInt8()\n")
+       fmt.Fprintf(buf, "\t\t\t// Check if CollectionNotDeclElementType flag 
is set\n")
+       fmt.Fprintf(buf, "\t\t\tif (collectFlag & 4) != 0 {\n")
+       fmt.Fprintf(buf, "\t\t\t\t// Read element type ID (we expect it but 
don't need to validate it for codegen)\n")
+       fmt.Fprintf(buf, "\t\t\t\t_ = buf.ReadVarInt32()\n")
+       fmt.Fprintf(buf, "\t\t\t}\n")
+
+       // Create slice
+       fmt.Fprintf(buf, "\t\t\t%s = make(%s, sliceLen)\n", fieldAccess, 
sliceType.String())
+
+       // Read elements
+       fmt.Fprintf(buf, "\t\t\tfor i := 0; i < sliceLen; i++ {\n")
+
+       // Generate element read code based on type
+       elemAccess := fmt.Sprintf("%s[i]", fieldAccess)
+       if err := generateSliceElementRead(buf, elemType, elemAccess); err != 
nil {
+               return err
+       }
+
+       fmt.Fprintf(buf, "\t\t\t}\n")
+       fmt.Fprintf(buf, "\t\t}\n")
+       fmt.Fprintf(buf, "\t}\n")
+
+       return nil
+}
+
+// generateSliceElementRead generates code to read a single slice element
+func generateSliceElementRead(buf *bytes.Buffer, elemType types.Type, 
elemAccess string) error {
+       // Handle basic types
+       if basic, ok := elemType.Underlying().(*types.Basic); ok {
+               switch basic.Kind() {
+               case types.Bool:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadBool()\n", 
elemAccess)
+               case types.Int8:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadInt8()\n", 
elemAccess)
+               case types.Int16:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadInt16()\n", 
elemAccess)
+               case types.Int32:
+                       fmt.Fprintf(buf, "\t\t\t\tif flag := buf.ReadInt8(); 
flag != -1 {\n")
+                       fmt.Fprintf(buf, "\t\t\t\t\treturn 
fmt.Errorf(\"expected NotNullValueFlag for slice element, got %%d\", flag)\n")
+                       fmt.Fprintf(buf, "\t\t\t\t}\n")
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadVarint32()\n", 
elemAccess)
+               case types.Int, types.Int64:
+                       fmt.Fprintf(buf, "\t\t\t\tif flag := buf.ReadInt8(); 
flag != -1 {\n")
+                       fmt.Fprintf(buf, "\t\t\t\t\treturn 
fmt.Errorf(\"expected NotNullValueFlag for slice element, got %%d\", flag)\n")
+                       fmt.Fprintf(buf, "\t\t\t\t}\n")
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadVarint64()\n", 
elemAccess)
+               case types.Uint8:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadByte_()\n", 
elemAccess)
+               case types.Uint16:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = 
uint16(buf.ReadInt16())\n", elemAccess)
+               case types.Uint32:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = 
uint32(buf.ReadInt32())\n", elemAccess)
+               case types.Uint, types.Uint64:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = 
uint64(buf.ReadInt64())\n", elemAccess)
+               case types.Float32:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadFloat32()\n", 
elemAccess)
+               case types.Float64:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadFloat64()\n", 
elemAccess)
+               case types.String:
+                       fmt.Fprintf(buf, "\t\t\t\tif flag := buf.ReadInt8(); 
flag != 0 {\n")
+                       fmt.Fprintf(buf, "\t\t\t\t\treturn 
fmt.Errorf(\"expected RefValueFlag for string element, got %%d\", flag)\n")
+                       fmt.Fprintf(buf, "\t\t\t\t}\n")
+                       fmt.Fprintf(buf, "\t\t\t\t%s = fory.ReadString(buf)\n", 
elemAccess)
+               default:
+                       fmt.Fprintf(buf, "\t\t\t\t// TODO: unsupported basic 
type %s\n", basic.String())
+               }
+               return nil
+       }
+
+       // Handle named types
+       if named, ok := elemType.(*types.Named); ok {
+               typeStr := named.String()
+               switch typeStr {
+               case "time.Time":
+                       fmt.Fprintf(buf, "\t\t\t\tusec := buf.ReadInt64()\n")
+                       fmt.Fprintf(buf, "\t\t\t\t%s = 
fory.CreateTimeFromUnixMicro(usec)\n", elemAccess)
+                       return nil
+               case "github.com/apache/fory/go/fory.Date":
+                       fmt.Fprintf(buf, "\t\t\t\tdays := buf.ReadInt32()\n")
+                       fmt.Fprintf(buf, "\t\t\t\t// Handle zero date marker\n")
+                       fmt.Fprintf(buf, "\t\t\t\tif days == int32(-2147483648) 
{\n")
+                       fmt.Fprintf(buf, "\t\t\t\t\t%s = fory.Date{Year: 0, 
Month: 0, Day: 0}\n", elemAccess)
+                       fmt.Fprintf(buf, "\t\t\t\t} else {\n")
+                       fmt.Fprintf(buf, "\t\t\t\t\tdiff := time.Duration(days) 
* 24 * time.Hour\n")
+                       fmt.Fprintf(buf, "\t\t\t\t\tt := time.Date(1970, 1, 1, 
0, 0, 0, 0, time.Local).Add(diff)\n")
+                       fmt.Fprintf(buf, "\t\t\t\t\t%s = fory.Date{Year: 
t.Year(), Month: t.Month(), Day: t.Day()}\n", elemAccess)
+                       fmt.Fprintf(buf, "\t\t\t\t}\n")
+                       return nil
+               }
+               // Check if it's a struct
+               if _, ok := named.Underlying().(*types.Struct); ok {
+                       fmt.Fprintf(buf, "\t\t\t\tf.ReadReferencable(buf, 
reflect.ValueOf(&%s).Elem())\n", elemAccess)
+                       return nil
+               }
+       }
+
+       // Handle struct types
+       if _, ok := elemType.Underlying().(*types.Struct); ok {
+               fmt.Fprintf(buf, "\t\t\t\tf.ReadReferencable(buf, 
reflect.ValueOf(&%s).Elem())\n", elemAccess)
+               return nil
+       }
+
+       fmt.Fprintf(buf, "\t\t\t\t// TODO: unsupported element type %s\n", 
elemType.String())
+       return nil
+}
+
+// generateSliceReadInline generates inline slice deserialization code to 
match encoder behavior exactly
+func generateSliceReadInline(buf *bytes.Buffer, sliceType *types.Slice, 
fieldAccess string) error {
+       elemType := sliceType.Elem()
+
+       // Read RefValueFlag first (slice is referencable)
+       fmt.Fprintf(buf, "\tif flag := buf.ReadInt8(); flag != 0 {\n")
+       fmt.Fprintf(buf, "\t\treturn fmt.Errorf(\"expected RefValueFlag for 
slice field, got %%d\", flag)\n")
+       fmt.Fprintf(buf, "\t}\n")
+
+       // Read slice length - use block scope to avoid variable name conflicts
+       fmt.Fprintf(buf, "\t{\n")
+       fmt.Fprintf(buf, "\t\tsliceLen := int(buf.ReadVarUint32())\n")
+       fmt.Fprintf(buf, "\t\tif sliceLen == 0 {\n")
+       fmt.Fprintf(buf, "\t\t\t%s = nil\n", fieldAccess)
+       fmt.Fprintf(buf, "\t\t} else {\n")
+
+       // Read collection header
+       fmt.Fprintf(buf, "\t\t\tcollectFlag := buf.ReadInt8()\n")
+       fmt.Fprintf(buf, "\t\t\t// We expect 12 (no ref tracking) or 13 (with 
ref tracking)\n")
+       fmt.Fprintf(buf, "\t\t\tif collectFlag != 12 && collectFlag != 13 {\n")
+       fmt.Fprintf(buf, "\t\t\t\treturn fmt.Errorf(\"unexpected collection 
flag: %%d\", collectFlag)\n")
+       fmt.Fprintf(buf, "\t\t\t}\n")
+
+       // Create slice
+       fmt.Fprintf(buf, "\t\t\t%s = make(%s, sliceLen)\n", fieldAccess, 
sliceType.String())
+
+       // Read elements
+       fmt.Fprintf(buf, "\t\t\tfor i := 0; i < sliceLen; i++ {\n")
+
+       // For each element, read NotNullValueFlag + TypeID + Value
+       fmt.Fprintf(buf, "\t\t\t\t// Read element NotNullValueFlag\n")
+       fmt.Fprintf(buf, "\t\t\t\tif flag := buf.ReadInt8(); flag != -1 {\n")
+       fmt.Fprintf(buf, "\t\t\t\t\treturn fmt.Errorf(\"expected 
NotNullValueFlag for element, got %%d\", flag)\n")
+       fmt.Fprintf(buf, "\t\t\t\t}\n")
+
+       // Read and verify element type ID
+       if err := generateElementTypeIDReadInline(buf, elemType); err != nil {
+               return err
+       }
+
+       // Read element value
+       if err := generateSliceElementReadInline(buf, elemType, 
fmt.Sprintf("%s[i]", fieldAccess)); err != nil {
+               return err
+       }
+
+       fmt.Fprintf(buf, "\t\t\t}\n")
+       fmt.Fprintf(buf, "\t\t}\n")
+       fmt.Fprintf(buf, "\t}\n")
+
+       return nil
+}
+
+// generateElementTypeIDReadInline generates element type ID verification
+func generateElementTypeIDReadInline(buf *bytes.Buffer, elemType types.Type) 
error {
+       // Handle basic types - verify the expected type ID
+       if basic, ok := elemType.Underlying().(*types.Basic); ok {
+               var expectedTypeID int
+               switch basic.Kind() {
+               case types.Bool:
+                       expectedTypeID = int(fory.BOOL)
+               case types.Int8:
+                       expectedTypeID = int(fory.INT8)
+               case types.Int16:
+                       expectedTypeID = int(fory.INT16)
+               case types.Int32:
+                       expectedTypeID = int(fory.INT32)
+               case types.Int, types.Int64:
+                       expectedTypeID = int(fory.INT64)
+               case types.Uint8:
+                       expectedTypeID = int(fory.UINT8)
+               case types.Uint16:
+                       expectedTypeID = int(fory.UINT16)
+               case types.Uint32:
+                       expectedTypeID = int(fory.UINT32)
+               case types.Uint, types.Uint64:
+                       expectedTypeID = int(fory.UINT64)
+               case types.Float32:
+                       expectedTypeID = int(fory.FLOAT)
+               case types.Float64:
+                       expectedTypeID = int(fory.DOUBLE)
+               case types.String:
+                       expectedTypeID = int(fory.STRING)
+               default:
+                       return fmt.Errorf("unsupported basic type for element 
type ID read: %s", basic.String())
+               }
+
+               fmt.Fprintf(buf, "\t\t\t\t// Read and verify element type ID\n")
+               fmt.Fprintf(buf, "\t\t\t\tif typeID := buf.ReadVarInt32(); 
typeID != %d {\n", expectedTypeID)
+               fmt.Fprintf(buf, "\t\t\t\t\treturn fmt.Errorf(\"expected 
element type ID %d, got %%d\", typeID)\n", expectedTypeID)
+               fmt.Fprintf(buf, "\t\t\t\t}\n")
+
+               return nil
+       }
+       return fmt.Errorf("unsupported element type for type ID read: %s", 
elemType.String())
+}
+
+// generateSliceElementReadInline generates code to read a single slice 
element value
+func generateSliceElementReadInline(buf *bytes.Buffer, elemType types.Type, 
elemAccess string) error {
+       // Handle basic types - read the actual value (type ID already verified 
above)
+       if basic, ok := elemType.Underlying().(*types.Basic); ok {
+               switch basic.Kind() {
+               case types.Bool:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadBool()\n", 
elemAccess)
+               case types.Int8:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadInt8()\n", 
elemAccess)
+               case types.Int16:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadInt16()\n", 
elemAccess)
+               case types.Int32:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadVarint32()\n", 
elemAccess)
+               case types.Int, types.Int64:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadVarint64()\n", 
elemAccess)
+               case types.Uint8:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadByte_()\n", 
elemAccess)
+               case types.Uint16:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = 
uint16(buf.ReadInt16())\n", elemAccess)
+               case types.Uint32:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = 
uint32(buf.ReadInt32())\n", elemAccess)
+               case types.Uint, types.Uint64:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = 
uint64(buf.ReadInt64())\n", elemAccess)
+               case types.Float32:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadFloat32()\n", 
elemAccess)
+               case types.Float64:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = buf.ReadFloat64()\n", 
elemAccess)
+               case types.String:
+                       fmt.Fprintf(buf, "\t\t\t\t%s = fory.ReadString(buf)\n", 
elemAccess)
+               default:
+                       return fmt.Errorf("unsupported basic type for element 
read: %s", basic.String())
+               }
+               return nil
+       }
+
+       // Handle interface types
+       if iface, ok := elemType.(*types.Interface); ok {
+               if iface.Empty() {
+                       // For interface{} elements, use ReadReferencable for 
dynamic type handling
+                       fmt.Fprintf(buf, "\t\t\t\tf.ReadReferencable(buf, 
reflect.ValueOf(&%s).Elem())\n", elemAccess)
+                       return nil
+               }
+       }
+
+       return fmt.Errorf("unsupported element type for read: %s", 
elemType.String())
+}
+
+// generateMapReadInline generates inline map deserialization code following 
the chunk-based format
+func generateMapReadInline(buf *bytes.Buffer, mapType *types.Map, fieldAccess 
string) error {
+       keyType := mapType.Key()
+       valueType := mapType.Elem()
+
+       // Check if key or value types are interface{}
+       keyIsInterface := false
+       valueIsInterface := false
+       if iface, ok := keyType.(*types.Interface); ok && iface.Empty() {
+               keyIsInterface = true
+       }
+       if iface, ok := valueType.(*types.Interface); ok && iface.Empty() {
+               valueIsInterface = true
+       }
+
+       // Read RefValueFlag first (map is referencable)
+       fmt.Fprintf(buf, "\tif flag := buf.ReadInt8(); flag != 0 {\n")
+       fmt.Fprintf(buf, "\t\treturn fmt.Errorf(\"expected RefValueFlag for map 
field, got %%d\", flag)\n")
+       fmt.Fprintf(buf, "\t}\n")
+
+       // Read map length
+       fmt.Fprintf(buf, "\t{\n")
+       fmt.Fprintf(buf, "\t\tmapLen := int(buf.ReadVarUint32())\n")
+       fmt.Fprintf(buf, "\t\tif mapLen == 0 {\n")
+       fmt.Fprintf(buf, "\t\t\t%s = make(%s)\n", fieldAccess, mapType.String())
+       fmt.Fprintf(buf, "\t\t} else {\n")
+       fmt.Fprintf(buf, "\t\t\t%s = make(%s, mapLen)\n", fieldAccess, 
mapType.String())
+       fmt.Fprintf(buf, "\t\t\tmapSize := mapLen\n")
+
+       // Read chunks
+       fmt.Fprintf(buf, "\t\t\tfor mapSize > 0 {\n")
+       fmt.Fprintf(buf, "\t\t\t\t// Read KV header\n")
+       fmt.Fprintf(buf, "\t\t\t\tkvHeader := buf.ReadUint8()\n")
+       fmt.Fprintf(buf, "\t\t\t\tchunkSize := int(buf.ReadUint8())\n")
+
+       // Parse header flags
+       fmt.Fprintf(buf, "\t\t\t\ttrackKeyRef := (kvHeader & 0x1) != 0\n")
+       fmt.Fprintf(buf, "\t\t\t\tkeyNotDeclared := (kvHeader & 0x4) != 0\n")
+       fmt.Fprintf(buf, "\t\t\t\ttrackValueRef := (kvHeader & 0x8) != 0\n")
+       fmt.Fprintf(buf, "\t\t\t\tvalueNotDeclared := (kvHeader & 0x20) != 0\n")
+       fmt.Fprintf(buf, "\t\t\t\t_ = trackKeyRef\n")
+       fmt.Fprintf(buf, "\t\t\t\t_ = keyNotDeclared\n")
+       fmt.Fprintf(buf, "\t\t\t\t_ = trackValueRef\n")
+       fmt.Fprintf(buf, "\t\t\t\t_ = valueNotDeclared\n")
+
+       // Read key-value pairs in this chunk
+       fmt.Fprintf(buf, "\t\t\t\tfor i := 0; i < chunkSize; i++ {\n")
+
+       // Read key
+       if keyIsInterface {
+               fmt.Fprintf(buf, "\t\t\t\t\tvar mapKey interface{}\n")
+               fmt.Fprintf(buf, "\t\t\t\t\tf.ReadReferencable(buf, 
reflect.ValueOf(&mapKey).Elem())\n")
+       } else {
+               // Declare key variable with appropriate type
+               keyVarType := getGoTypeString(keyType)
+               fmt.Fprintf(buf, "\t\t\t\t\tvar mapKey %s\n", keyVarType)
+               if err := generateMapKeyRead(buf, keyType, "mapKey"); err != 
nil {
+                       return err
+               }
+       }
+
+       // Read value
+       if valueIsInterface {
+               fmt.Fprintf(buf, "\t\t\t\t\tvar mapValue interface{}\n")
+               fmt.Fprintf(buf, "\t\t\t\t\tf.ReadReferencable(buf, 
reflect.ValueOf(&mapValue).Elem())\n")
+       } else {
+               // Declare value variable with appropriate type
+               valueVarType := getGoTypeString(valueType)
+               fmt.Fprintf(buf, "\t\t\t\t\tvar mapValue %s\n", valueVarType)
+               if err := generateMapValueRead(buf, valueType, "mapValue"); err 
!= nil {
+                       return err
+               }
+       }
+
+       // Set key-value pair in map
+       fmt.Fprintf(buf, "\t\t\t\t\t%s[mapKey] = mapValue\n", fieldAccess)
+
+       fmt.Fprintf(buf, "\t\t\t\t}\n") // end chunk loop
+       fmt.Fprintf(buf, "\t\t\t\tmapSize -= chunkSize\n")
+       fmt.Fprintf(buf, "\t\t\t}\n") // end mapSize > 0 loop
+
+       fmt.Fprintf(buf, "\t\t}\n") // end else (mapLen > 0)
+       fmt.Fprintf(buf, "\t}\n")   // end block scope
+
+       return nil
+}
+
+// getGoTypeString returns the Go type string for a types.Type
+func getGoTypeString(t types.Type) string {
+       // Handle basic types
+       if basic, ok := t.Underlying().(*types.Basic); ok {
+               switch basic.Kind() {
+               case types.Int:
+                       return "int"
+               case types.String:
+                       return "string"
+               default:
+                       return t.String()
+               }
+       }
+       return t.String()
+}
+
+// generateMapKeyRead generates code to read a map key
+func generateMapKeyRead(buf *bytes.Buffer, keyType types.Type, varName string) 
error {
+       // For basic types, match reflection's serializer behavior
+       if basic, ok := keyType.Underlying().(*types.Basic); ok {
+               switch basic.Kind() {
+               case types.Int:
+                       // intSerializer uses ReadInt64, not ReadVarint64
+                       fmt.Fprintf(buf, "\t\t\t\t\t%s = 
int(buf.ReadInt64())\n", varName)
+               case types.String:
+                       // stringSerializer is referencable, need to use 
ReadReferencable
+                       fmt.Fprintf(buf, "\t\t\t\t\tf.ReadReferencable(buf, 
reflect.ValueOf(&%s).Elem())\n", varName)
+               default:
+                       return fmt.Errorf("unsupported map key type: %v", 
keyType)
+               }
+               return nil
+       }
+
+       // For other types, use ReadReferencable
+       fmt.Fprintf(buf, "\t\t\t\t\tf.ReadReferencable(buf, 
reflect.ValueOf(&%s).Elem())\n", varName)
+       return nil
+}
+
+// generateMapValueRead generates code to read a map value
+func generateMapValueRead(buf *bytes.Buffer, valueType types.Type, varName 
string) error {
+       // For basic types, match reflection's serializer behavior
+       if basic, ok := valueType.Underlying().(*types.Basic); ok {
+               switch basic.Kind() {
+               case types.Int:
+                       // intSerializer uses ReadInt64, not ReadVarint64
+                       fmt.Fprintf(buf, "\t\t\t\t\t%s = 
int(buf.ReadInt64())\n", varName)
+               case types.String:
+                       // stringSerializer is referencable, need to use 
ReadReferencable
+                       fmt.Fprintf(buf, "\t\t\t\t\tf.ReadReferencable(buf, 
reflect.ValueOf(&%s).Elem())\n", varName)
+               default:
+                       return fmt.Errorf("unsupported map value type: %v", 
valueType)
+               }
+               return nil
+       }
+
+       // For other types, use ReadReferencable
+       fmt.Fprintf(buf, "\t\t\t\t\tf.ReadReferencable(buf, 
reflect.ValueOf(&%s).Elem())\n", varName)
+       return nil
+}
diff --git a/go/fory/codegen/encoder.go b/go/fory/codegen/encoder.go
index 72a5e94cd..804aac6d1 100644
--- a/go/fory/codegen/encoder.go
+++ b/go/fory/codegen/encoder.go
@@ -21,6 +21,8 @@ import (
        "bytes"
        "fmt"
        "go/types"
+
+       "github.com/apache/fory/go/fory"
 )
 
 // generateWriteTyped generates the strongly-typed Write method
@@ -102,28 +104,40 @@ func generateFieldWriteTyped(buf *bytes.Buffer, field 
*FieldInfo) error {
        if basic, ok := field.Type.Underlying().(*types.Basic); ok {
                switch basic.Kind() {
                case types.Bool:
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
                        fmt.Fprintf(buf, "\tbuf.WriteBool(%s)\n", fieldAccess)
                case types.Int8:
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
                        fmt.Fprintf(buf, "\tbuf.WriteInt8(%s)\n", fieldAccess)
                case types.Int16:
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
                        fmt.Fprintf(buf, "\tbuf.WriteInt16(%s)\n", fieldAccess)
                case types.Int32:
-                       fmt.Fprintf(buf, "\tbuf.WriteInt32(%s)\n", fieldAccess)
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
+                       fmt.Fprintf(buf, "\tbuf.WriteVarint32(%s)\n", 
fieldAccess)
                case types.Int, types.Int64:
-                       fmt.Fprintf(buf, "\tbuf.WriteInt64(%s)\n", fieldAccess)
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
+                       fmt.Fprintf(buf, "\tbuf.WriteVarint64(%s)\n", 
fieldAccess)
                case types.Uint8:
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
                        fmt.Fprintf(buf, "\tbuf.WriteByte_(%s)\n", fieldAccess)
                case types.Uint16:
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
                        fmt.Fprintf(buf, "\tbuf.WriteInt16(int16(%s))\n", 
fieldAccess)
                case types.Uint32:
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
                        fmt.Fprintf(buf, "\tbuf.WriteInt32(int32(%s))\n", 
fieldAccess)
                case types.Uint, types.Uint64:
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
                        fmt.Fprintf(buf, "\tbuf.WriteInt64(int64(%s))\n", 
fieldAccess)
                case types.Float32:
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
                        fmt.Fprintf(buf, "\tbuf.WriteFloat32(%s)\n", 
fieldAccess)
                case types.Float64:
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(-1) // 
NotNullValueFlag\n")
                        fmt.Fprintf(buf, "\tbuf.WriteFloat64(%s)\n", 
fieldAccess)
                case types.String:
+                       fmt.Fprintf(buf, "\tbuf.WriteInt8(0) // RefValueFlag\n")
                        fmt.Fprintf(buf, "\tfory.WriteString(buf, %s)\n", 
fieldAccess)
                default:
                        fmt.Fprintf(buf, "\t// TODO: unsupported basic type 
%s\n", basic.String())
@@ -131,6 +145,57 @@ func generateFieldWriteTyped(buf *bytes.Buffer, field 
*FieldInfo) error {
                return nil
        }
 
+       // Handle slice types
+       if slice, ok := field.Type.(*types.Slice); ok {
+               elemType := slice.Elem()
+               // Check if element type is interface{} (dynamic type)
+               if iface, ok := elemType.(*types.Interface); ok && 
iface.Empty() {
+                       // For []interface{}, we need to manually implement the 
serialization
+                       // because WriteReferencable produces incorrect length 
encoding
+                       fmt.Fprintf(buf, "\t// Dynamic slice []interface{} 
handling - manual serialization\n")
+                       fmt.Fprintf(buf, "\tif %s == nil {\n", fieldAccess)
+                       fmt.Fprintf(buf, "\t\tbuf.WriteInt8(-3) // null value 
flag\n")
+                       fmt.Fprintf(buf, "\t} else {\n")
+                       fmt.Fprintf(buf, "\t\t// Write reference flag for the 
slice itself\n")
+                       fmt.Fprintf(buf, "\t\tbuf.WriteInt8(0) // 
RefValueFlag\n")
+                       fmt.Fprintf(buf, "\t\t// Write slice length\n")
+                       fmt.Fprintf(buf, 
"\t\tbuf.WriteVarUint32(uint32(len(%s)))\n", fieldAccess)
+                       fmt.Fprintf(buf, "\t\t// Write collection flags (13 = 
NotDeclElementType + NotSameType + TrackingRef for dynamic slices)\n")
+                       fmt.Fprintf(buf, "\t\t// Always write collection flags 
with tracking ref enabled (13)\n")
+                       fmt.Fprintf(buf, "\t\t// This matches the reflection 
implementation which uses NewFory(true)\n")
+                       fmt.Fprintf(buf, "\t\tbuf.WriteInt8(13) // 12 + 1 
(CollectionTrackingRef)\n")
+                       fmt.Fprintf(buf, "\t\t// Write each element using 
WriteReferencable\n")
+                       fmt.Fprintf(buf, "\t\tfor _, elem := range %s {\n", 
fieldAccess)
+                       fmt.Fprintf(buf, "\t\t\tf.WriteReferencable(buf, 
reflect.ValueOf(elem))\n")
+                       fmt.Fprintf(buf, "\t\t}\n")
+                       fmt.Fprintf(buf, "\t}\n")
+                       return nil
+               }
+               // For static element types, use optimized inline generation
+               if err := generateSliceWriteInline(buf, slice, fieldAccess); 
err != nil {
+                       return err
+               }
+               return nil
+       }
+
+       // Handle map types
+       if mapType, ok := field.Type.(*types.Map); ok {
+               // For map types, we'll use manual serialization following the 
chunk-based format
+               if err := generateMapWriteInline(buf, mapType, fieldAccess); 
err != nil {
+                       return err
+               }
+               return nil
+       }
+
+       // Handle interface types
+       if iface, ok := field.Type.(*types.Interface); ok {
+               if iface.Empty() {
+                       // For interface{}, use WriteReferencable for dynamic 
type handling
+                       fmt.Fprintf(buf, "\tf.WriteReferencable(buf, 
reflect.ValueOf(%s))\n", fieldAccess)
+                       return nil
+               }
+       }
+
        // Handle struct types
        if _, ok := field.Type.Underlying().(*types.Struct); ok {
                fmt.Fprintf(buf, "\tf.WriteReferencable(buf, 
reflect.ValueOf(%s))\n", fieldAccess)
@@ -140,3 +205,387 @@ func generateFieldWriteTyped(buf *bytes.Buffer, field 
*FieldInfo) error {
        fmt.Fprintf(buf, "\t// TODO: unsupported type %s\n", 
field.Type.String())
        return nil
 }
+
+// generateElementTypeIDWrite generates code to write the element type ID for 
slice serialization
+func generateElementTypeIDWrite(buf *bytes.Buffer, elemType types.Type) error {
+       // Handle basic types
+       if basic, ok := elemType.Underlying().(*types.Basic); ok {
+               switch basic.Kind() {
+               case types.Bool:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // BOOL\n", 
fory.BOOL)
+               case types.Int8:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // INT8\n", 
fory.INT8)
+               case types.Int16:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
INT16\n", fory.INT16)
+               case types.Int32:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
INT32\n", fory.INT32)
+               case types.Int, types.Int64:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
INT64\n", fory.INT64)
+               case types.Uint8:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
UINT8\n", fory.UINT8)
+               case types.Uint16:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
UINT16\n", fory.UINT16)
+               case types.Uint32:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
UINT32\n", fory.UINT32)
+               case types.Uint, types.Uint64:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
UINT64\n", fory.UINT64)
+               case types.Float32:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
FLOAT\n", fory.FLOAT)
+               case types.Float64:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
DOUBLE\n", fory.DOUBLE)
+               case types.String:
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
STRING\n", fory.STRING)
+               default:
+                       return fmt.Errorf("unsupported basic type for element 
type ID: %s", basic.String())
+               }
+               return nil
+       }
+
+       // Handle named types
+       if named, ok := elemType.(*types.Named); ok {
+               typeStr := named.String()
+               switch typeStr {
+               case "time.Time":
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
TIMESTAMP\n", fory.TIMESTAMP)
+                       return nil
+               case "github.com/apache/fory/go/fory.Date":
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
LOCAL_DATE\n", fory.LOCAL_DATE)
+                       return nil
+               }
+               // Check if it's a struct
+               if _, ok := named.Underlying().(*types.Struct); ok {
+                       fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // 
NAMED_STRUCT\n", fory.NAMED_STRUCT)
+                       return nil
+               }
+       }
+
+       // Handle struct types
+       if _, ok := elemType.Underlying().(*types.Struct); ok {
+               fmt.Fprintf(buf, "\t\tbuf.WriteVarInt32(%d) // NAMED_STRUCT\n", 
fory.NAMED_STRUCT)
+               return nil
+       }
+
+       return fmt.Errorf("unsupported element type for type ID: %s", 
elemType.String())
+}
+
+// generateSliceWriteInline generates inline slice serialization code to match 
reflection behavior exactly
+func generateSliceWriteInline(buf *bytes.Buffer, sliceType *types.Slice, 
fieldAccess string) error {
+       elemType := sliceType.Elem()
+
+       // Write RefValueFlag first (slice is referencable)
+       fmt.Fprintf(buf, "\tbuf.WriteInt8(0) // RefValueFlag for slice\n")
+
+       // Write slice length - use block scope to avoid variable name conflicts
+       fmt.Fprintf(buf, "\t{\n")
+       fmt.Fprintf(buf, "\t\tsliceLen := 0\n")
+       fmt.Fprintf(buf, "\t\tif %s != nil {\n", fieldAccess)
+       fmt.Fprintf(buf, "\t\t\tsliceLen = len(%s)\n", fieldAccess)
+       fmt.Fprintf(buf, "\t\t}\n")
+       fmt.Fprintf(buf, "\t\tbuf.WriteVarUint32(uint32(sliceLen))\n")
+
+       // Write collection header and elements for non-empty slice
+       fmt.Fprintf(buf, "\t\tif sliceLen > 0 {\n")
+
+       // For codegen, follow reflection's behavior exactly:
+       // Set CollectionNotDeclElementType (0b0100 = 4) and 
CollectionNotSameType (0b1000 = 8)
+       // Add CollectionTrackingRef (0b0001 = 1) when reference tracking is 
enabled
+       fmt.Fprintf(buf, "\t\t\tcollectFlag := 12 // 
CollectionNotDeclElementType + CollectionNotSameType\n")
+       fmt.Fprintf(buf, "\t\t\t// Access private field f.refTracking using 
reflection to match behavior\n")
+       fmt.Fprintf(buf, "\t\t\tforyValue := reflect.ValueOf(f).Elem()\n")
+       fmt.Fprintf(buf, "\t\t\trefTrackingField := 
foryValue.FieldByName(\"refTracking\")\n")
+       fmt.Fprintf(buf, "\t\t\tif refTrackingField.IsValid() && 
refTrackingField.Bool() {\n")
+       fmt.Fprintf(buf, "\t\t\t\tcollectFlag |= 1 // Add 
CollectionTrackingRef\n")
+       fmt.Fprintf(buf, "\t\t\t}\n")
+       fmt.Fprintf(buf, "\t\t\tbuf.WriteInt8(int8(collectFlag))\n")
+
+       // For each element, write type info + value (because 
CollectionNotSameType is set)
+       fmt.Fprintf(buf, "\t\t\tfor _, elem := range %s {\n", fieldAccess)
+       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteInt8(-1) // NotNullValueFlag\n")
+
+       // Write element type ID
+       if err := generateElementTypeIDWriteInline(buf, elemType); err != nil {
+               return err
+       }
+
+       // Write element value
+       if err := generateSliceElementWriteInline(buf, elemType, "elem"); err 
!= nil {
+               return err
+       }
+
+       fmt.Fprintf(buf, "\t\t\t}\n")
+       fmt.Fprintf(buf, "\t\t}\n")
+       fmt.Fprintf(buf, "\t}\n")
+
+       return nil
+}
+
+// generateMapWriteInline generates inline map serialization code following 
the chunk-based format
+func generateMapWriteInline(buf *bytes.Buffer, mapType *types.Map, fieldAccess 
string) error {
+       keyType := mapType.Key()
+       valueType := mapType.Elem()
+
+       // Check if key or value types are interface{}
+       keyIsInterface := false
+       valueIsInterface := false
+       if iface, ok := keyType.(*types.Interface); ok && iface.Empty() {
+               keyIsInterface = true
+       }
+       if iface, ok := valueType.(*types.Interface); ok && iface.Empty() {
+               valueIsInterface = true
+       }
+
+       // Write RefValueFlag first (map is referencable)
+       fmt.Fprintf(buf, "\tbuf.WriteInt8(0) // RefValueFlag for map\n")
+
+       // Write map length
+       fmt.Fprintf(buf, "\t{\n")
+       fmt.Fprintf(buf, "\t\tmapLen := 0\n")
+       fmt.Fprintf(buf, "\t\tif %s != nil {\n", fieldAccess)
+       fmt.Fprintf(buf, "\t\t\tmapLen = len(%s)\n", fieldAccess)
+       fmt.Fprintf(buf, "\t\t}\n")
+       fmt.Fprintf(buf, "\t\tbuf.WriteVarUint32(uint32(mapLen))\n")
+
+       // Write chunks for non-empty map
+       fmt.Fprintf(buf, "\t\tif mapLen > 0 {\n")
+
+       // Calculate KV header based on types
+       fmt.Fprintf(buf, "\t\t\t// Calculate KV header flags\n")
+       fmt.Fprintf(buf, "\t\t\tkvHeader := uint8(0)\n")
+
+       // Check if ref tracking is enabled
+       fmt.Fprintf(buf, "\t\t\tforyValue := reflect.ValueOf(f).Elem()\n")
+       fmt.Fprintf(buf, "\t\t\trefTrackingField := 
foryValue.FieldByName(\"refTracking\")\n")
+       fmt.Fprintf(buf, "\t\t\tisRefTracking := refTrackingField.IsValid() && 
refTrackingField.Bool()\n")
+       fmt.Fprintf(buf, "\t\t\t_ = isRefTracking // Mark as used to avoid 
warning\n")
+
+       // Set header flags based on type properties
+       if !keyIsInterface {
+               // For concrete key types, check if they're referencable
+               if isReferencableType(keyType) {
+                       fmt.Fprintf(buf, "\t\t\tif isRefTracking {\n")
+                       fmt.Fprintf(buf, "\t\t\t\tkvHeader |= 0x1 // track key 
ref\n")
+                       fmt.Fprintf(buf, "\t\t\t}\n")
+               }
+       } else {
+               // For interface{} keys, always set not declared type flag
+               fmt.Fprintf(buf, "\t\t\tkvHeader |= 0x4 // key type not 
declared\n")
+       }
+
+       if !valueIsInterface {
+               // For concrete value types, check if they're referencable
+               if isReferencableType(valueType) {
+                       fmt.Fprintf(buf, "\t\t\tif isRefTracking {\n")
+                       fmt.Fprintf(buf, "\t\t\t\tkvHeader |= 0x8 // track 
value ref\n")
+                       fmt.Fprintf(buf, "\t\t\t}\n")
+               }
+       } else {
+               // For interface{} values, always set not declared type flag
+               fmt.Fprintf(buf, "\t\t\tkvHeader |= 0x20 // value type not 
declared\n")
+       }
+
+       // Write map elements in chunks
+       fmt.Fprintf(buf, "\t\t\tchunkSize := 0\n")
+       fmt.Fprintf(buf, "\t\t\t_ = buf.WriterIndex() // chunkHeaderOffset\n")
+       fmt.Fprintf(buf, "\t\t\tbuf.WriteInt8(int8(kvHeader)) // KV header\n")
+       fmt.Fprintf(buf, "\t\t\tchunkSizeOffset := buf.WriterIndex()\n")
+       fmt.Fprintf(buf, "\t\t\tbuf.WriteInt8(0) // placeholder for chunk 
size\n")
+
+       fmt.Fprintf(buf, "\t\t\tfor mapKey, mapValue := range %s {\n", 
fieldAccess)
+
+       // Write key
+       if keyIsInterface {
+               fmt.Fprintf(buf, "\t\t\t\tf.WriteReferencable(buf, 
reflect.ValueOf(mapKey))\n")
+       } else {
+               if err := generateMapKeyWrite(buf, keyType, "mapKey"); err != 
nil {
+                       return err
+               }
+       }
+
+       // Write value
+       if valueIsInterface {
+               fmt.Fprintf(buf, "\t\t\t\tf.WriteReferencable(buf, 
reflect.ValueOf(mapValue))\n")
+       } else {
+               if err := generateMapValueWrite(buf, valueType, "mapValue"); 
err != nil {
+                       return err
+               }
+       }
+
+       fmt.Fprintf(buf, "\t\t\t\tchunkSize++\n")
+       fmt.Fprintf(buf, "\t\t\t\tif chunkSize >= 255 {\n")
+       fmt.Fprintf(buf, "\t\t\t\t\t// Write chunk size and start new chunk\n")
+       fmt.Fprintf(buf, "\t\t\t\t\tbuf.PutUint8(chunkSizeOffset, 
uint8(chunkSize))\n")
+       fmt.Fprintf(buf, "\t\t\t\t\tif len(%s) > chunkSize {\n", fieldAccess)
+       fmt.Fprintf(buf, "\t\t\t\t\t\tchunkSize = 0\n")
+       fmt.Fprintf(buf, "\t\t\t\t\t\t_ = buf.WriterIndex() // 
chunkHeaderOffset\n")
+       fmt.Fprintf(buf, "\t\t\t\t\t\tbuf.WriteInt8(int8(kvHeader)) // KV 
header\n")
+       fmt.Fprintf(buf, "\t\t\t\t\t\tchunkSizeOffset = buf.WriterIndex()\n")
+       fmt.Fprintf(buf, "\t\t\t\t\t\tbuf.WriteInt8(0) // placeholder for chunk 
size\n")
+       fmt.Fprintf(buf, "\t\t\t\t\t}\n")
+       fmt.Fprintf(buf, "\t\t\t\t}\n")
+
+       fmt.Fprintf(buf, "\t\t\t}\n") // end for loop
+
+       // Write final chunk size
+       fmt.Fprintf(buf, "\t\t\tif chunkSize > 0 {\n")
+       fmt.Fprintf(buf, "\t\t\t\tbuf.PutUint8(chunkSizeOffset, 
uint8(chunkSize))\n")
+       fmt.Fprintf(buf, "\t\t\t}\n")
+
+       fmt.Fprintf(buf, "\t\t}\n") // end if mapLen > 0
+       fmt.Fprintf(buf, "\t}\n")   // end block scope
+
+       return nil
+}
+
+// isReferencableType checks if a type is referencable (needs reference 
tracking)
+func isReferencableType(t types.Type) bool {
+       // Handle pointer types
+       if _, ok := t.(*types.Pointer); ok {
+               return true
+       }
+
+       // Basic types and their underlying types
+       if basic, ok := t.Underlying().(*types.Basic); ok {
+               return basic.Kind() == types.String
+       }
+
+       // Slices, maps, and interfaces are referencable
+       switch t.Underlying().(type) {
+       case *types.Slice, *types.Map, *types.Interface:
+               return true
+       }
+
+       // Structs are referencable
+       if _, ok := t.Underlying().(*types.Struct); ok {
+               return true
+       }
+
+       return false
+}
+
+// generateMapKeyWrite generates code to write a map key
+func generateMapKeyWrite(buf *bytes.Buffer, keyType types.Type, varName 
string) error {
+       // For basic types, match reflection's serializer behavior
+       if basic, ok := keyType.Underlying().(*types.Basic); ok {
+               switch basic.Kind() {
+               case types.Int:
+                       // intSerializer uses WriteInt64, not WriteVarint64
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteInt64(int64(%s))\n", 
varName)
+               case types.String:
+                       // stringSerializer is referencable, need to use 
WriteReferencable
+                       fmt.Fprintf(buf, "\t\t\t\tf.WriteReferencable(buf, 
reflect.ValueOf(%s))\n", varName)
+               default:
+                       return fmt.Errorf("unsupported map key type: %v", 
keyType)
+               }
+               return nil
+       }
+
+       // For other types, use WriteReferencable
+       fmt.Fprintf(buf, "\t\t\t\tf.WriteReferencable(buf, 
reflect.ValueOf(%s))\n", varName)
+       return nil
+}
+
+// generateMapValueWrite generates code to write a map value
+func generateMapValueWrite(buf *bytes.Buffer, valueType types.Type, varName 
string) error {
+       // For basic types, match reflection's serializer behavior
+       if basic, ok := valueType.Underlying().(*types.Basic); ok {
+               switch basic.Kind() {
+               case types.Int:
+                       // intSerializer uses WriteInt64, not WriteVarint64
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteInt64(int64(%s))\n", 
varName)
+               case types.String:
+                       // stringSerializer is referencable, need to use 
WriteReferencable
+                       fmt.Fprintf(buf, "\t\t\t\tf.WriteReferencable(buf, 
reflect.ValueOf(%s))\n", varName)
+               default:
+                       return fmt.Errorf("unsupported map value type: %v", 
valueType)
+               }
+               return nil
+       }
+
+       // For other types, use WriteReferencable
+       fmt.Fprintf(buf, "\t\t\t\tf.WriteReferencable(buf, 
reflect.ValueOf(%s))\n", varName)
+       return nil
+}
+
+// generateElementTypeIDWriteInline generates element type ID write with 
specific indentation
+func generateElementTypeIDWriteInline(buf *bytes.Buffer, elemType types.Type) 
error {
+       // Handle basic types
+       if basic, ok := elemType.Underlying().(*types.Basic); ok {
+               switch basic.Kind() {
+               case types.Bool:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
BOOL\n", fory.BOOL)
+               case types.Int8:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
INT8\n", fory.INT8)
+               case types.Int16:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
INT16\n", fory.INT16)
+               case types.Int32:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
INT32\n", fory.INT32)
+               case types.Int, types.Int64:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
INT64\n", fory.INT64)
+               case types.Uint8:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
UINT8\n", fory.UINT8)
+               case types.Uint16:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
UINT16\n", fory.UINT16)
+               case types.Uint32:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
UINT32\n", fory.UINT32)
+               case types.Uint, types.Uint64:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
UINT64\n", fory.UINT64)
+               case types.Float32:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
FLOAT\n", fory.FLOAT)
+               case types.Float64:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
DOUBLE\n", fory.DOUBLE)
+               case types.String:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarInt32(%d) // 
STRING\n", fory.STRING)
+               default:
+                       return fmt.Errorf("unsupported basic type for element 
type ID: %s", basic.String())
+               }
+               return nil
+       }
+       return fmt.Errorf("unsupported element type for type ID: %s", 
elemType.String())
+}
+
+// generateSliceElementWriteInline generates code to write a single slice 
element value
+func generateSliceElementWriteInline(buf *bytes.Buffer, elemType types.Type, 
elemAccess string) error {
+       // Handle basic types - write the actual value without type info (type 
already written above)
+       if basic, ok := elemType.Underlying().(*types.Basic); ok {
+               switch basic.Kind() {
+               case types.Bool:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteBool(%s)\n", 
elemAccess)
+               case types.Int8:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteInt8(%s)\n", 
elemAccess)
+               case types.Int16:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteInt16(%s)\n", 
elemAccess)
+               case types.Int32:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarint32(%s)\n", 
elemAccess)
+               case types.Int, types.Int64:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteVarint64(%s)\n", 
elemAccess)
+               case types.Uint8:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteByte_(%s)\n", 
elemAccess)
+               case types.Uint16:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteInt16(int16(%s))\n", 
elemAccess)
+               case types.Uint32:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteInt32(int32(%s))\n", 
elemAccess)
+               case types.Uint, types.Uint64:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteInt64(int64(%s))\n", 
elemAccess)
+               case types.Float32:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteFloat32(%s)\n", 
elemAccess)
+               case types.Float64:
+                       fmt.Fprintf(buf, "\t\t\t\tbuf.WriteFloat64(%s)\n", 
elemAccess)
+               case types.String:
+                       fmt.Fprintf(buf, "\t\t\t\tfory.WriteString(buf, %s)\n", 
elemAccess)
+               default:
+                       return fmt.Errorf("unsupported basic type for element 
write: %s", basic.String())
+               }
+               return nil
+       }
+
+       // Handle interface types
+       if iface, ok := elemType.(*types.Interface); ok {
+               if iface.Empty() {
+                       // For interface{} elements, use WriteReferencable for 
dynamic type handling
+                       fmt.Fprintf(buf, "\t\t\t\tf.WriteReferencable(buf, 
reflect.ValueOf(%s))\n", elemAccess)
+                       return nil
+               }
+       }
+
+       return fmt.Errorf("unsupported element type for write: %s", 
elemType.String())
+}
diff --git a/go/fory/codegen/guard.go b/go/fory/codegen/guard.go
index c346f439d..b73aed571 100644
--- a/go/fory/codegen/guard.go
+++ b/go/fory/codegen/guard.go
@@ -53,14 +53,15 @@ func generateStructGuard(buf *bytes.Buffer, structInfo 
StructInfo) {
        buf.WriteString(fmt.Sprintf("// Snapshot of %s's underlying type at 
generation time.\n", typeName))
        buf.WriteString(fmt.Sprintf("type %s struct {\n", expectedTypeName))
 
-       // Sort fields to ensure consistent ordering (using pointers)
-       fields := make([]*FieldInfo, len(structInfo.Fields))
-       copy(fields, structInfo.Fields)
-       sort.Slice(fields, func(i, j int) bool {
-               return fields[i].GoName < fields[j].GoName
+       // Sort fields by their original index to match the struct definition
+       // This is important for the compile-time guard to work correctly
+       originalFields := make([]*FieldInfo, len(structInfo.Fields))
+       copy(originalFields, structInfo.Fields)
+       sort.Slice(originalFields, func(i, j int) bool {
+               return originalFields[i].Index < originalFields[j].Index
        })
 
-       for _, field := range fields {
+       for _, field := range originalFields {
                buf.WriteString(fmt.Sprintf("\t%s %s", field.GoName, 
formatFieldType(*field)))
 
                // Add struct tag if present (we'll extract it from the 
original struct)
diff --git a/go/fory/codegen/utils.go b/go/fory/codegen/utils.go
index 00dde6424..18c5de055 100644
--- a/go/fory/codegen/utils.go
+++ b/go/fory/codegen/utils.go
@@ -18,11 +18,12 @@
 package codegen
 
 import (
-       "crypto/md5"
-       "encoding/binary"
+       "fmt"
        "go/types"
        "sort"
        "unicode"
+
+       "github.com/apache/fory/go/fory"
 )
 
 // FieldInfo contains metadata about a struct field
@@ -62,6 +63,18 @@ func isSupportedFieldType(t types.Type) bool {
                t = ptr.Elem()
        }
 
+       // Check slice types
+       if slice, ok := t.(*types.Slice); ok {
+               // Check if element type is supported
+               return isSupportedFieldType(slice.Elem())
+       }
+
+       // Check map types
+       if mapType, ok := t.(*types.Map); ok {
+               // Check if both key and value types are supported
+               return isSupportedFieldType(mapType.Key()) && 
isSupportedFieldType(mapType.Elem())
+       }
+
        // Check named types
        if named, ok := t.(*types.Named); ok {
                typeStr := named.String()
@@ -75,6 +88,14 @@ func isSupportedFieldType(t types.Type) bool {
                }
        }
 
+       // Check interface types
+       if iface, ok := t.(*types.Interface); ok {
+               // Support empty interface{} for dynamic types
+               if iface.Empty() {
+                       return true
+               }
+       }
+
        // Check basic types
        if basic, ok := t.Underlying().(*types.Basic); ok {
                switch basic.Kind() {
@@ -105,10 +126,8 @@ func isPrimitiveType(t types.Type) bool {
                }
        }
 
-       // String is also considered primitive in Fory context but nullable
-       if basic, ok := t.Underlying().(*types.Basic); ok && basic.Kind() == 
types.String {
-               return true
-       }
+       // String is NOT considered primitive for sorting purposes (it goes to 
final group)
+       // This matches reflection's behavior where STRING goes to final group, 
not boxed group
 
        return false
 }
@@ -120,6 +139,23 @@ func getTypeID(t types.Type) string {
                t = ptr.Elem()
        }
 
+       // Check slice types
+       if _, ok := t.(*types.Slice); ok {
+               return "LIST"
+       }
+
+       // Check map types
+       if _, ok := t.(*types.Map); ok {
+               return "MAP"
+       }
+
+       // Check interface types
+       if iface, ok := t.(*types.Interface); ok {
+               if iface.Empty() {
+                       return "INTERFACE" // Use a placeholder for empty 
interface{}
+               }
+       }
+
        // Check named types first
        if named, ok := t.(*types.Named); ok {
                typeStr := named.String()
@@ -194,38 +230,55 @@ func getPrimitiveSize(t types.Type) int {
 }
 
 // getTypeIDValue returns numeric value for type ID for sorting
+// This uses the actual Fory TypeId constants for accuracy
 func getTypeIDValue(typeID string) int {
-       // Map Fory TypeIDs to numeric values for sorting
-       typeIDMap := map[string]int{
-               "BOOL":         1,
-               "INT8":         2,
-               "INT16":        3,
-               "INT32":        4,
-               "INT64":        5,
-               "UINT8":        6,
-               "UINT16":       7,
-               "UINT32":       8,
-               "UINT64":       9,
-               "FLOAT32":      10,
-               "FLOAT64":      11,
-               "STRING":       12,
-               "TIMESTAMP":    20,
-               "LOCAL_DATE":   21,
-               "NAMED_STRUCT": 30,
+       switch typeID {
+       case "BOOL":
+               return int(fory.BOOL) // 1
+       case "INT8":
+               return int(fory.INT8) // 2
+       case "INT16":
+               return int(fory.INT16) // 3
+       case "INT32":
+               return int(fory.INT32) // 4
+       case "INT64":
+               return int(fory.INT64) // 6
+       case "UINT8":
+               return int(fory.UINT8) // 100
+       case "UINT16":
+               return int(fory.UINT16) // 101
+       case "UINT32":
+               return int(fory.UINT32) // 102
+       case "UINT64":
+               return int(fory.UINT64) // 103
+       case "FLOAT32":
+               return int(fory.FLOAT) // 10
+       case "FLOAT64":
+               return int(fory.DOUBLE) // 11
+       case "STRING":
+               return int(fory.STRING) // 12
+       case "TIMESTAMP":
+               return int(fory.TIMESTAMP) // 25
+       case "LOCAL_DATE":
+               return int(fory.LOCAL_DATE) // 26
+       case "NAMED_STRUCT":
+               return int(fory.NAMED_STRUCT) // 17
+       case "LIST":
+               return int(fory.LIST) // 21
+       case "MAP":
+               return int(fory.MAP) // 23
+       default:
+               return 999 // Unknown types sort last
        }
-
-       if val, ok := typeIDMap[typeID]; ok {
-               return val
-       }
-       return 999
 }
 
-// sortFields sorts fields according to Fory protocol
+// sortFields sorts fields according to Fory protocol specification
+// This matches the reflection-based sorting exactly for cross-language 
compatibility
 func sortFields(fields []*FieldInfo) {
        sort.Slice(fields, func(i, j int) bool {
                f1, f2 := fields[i], fields[j]
 
-               // Group primitives first
+               // Group primitives first (matching reflection's boxed group)
                if f1.IsPrimitive && !f2.IsPrimitive {
                        return true
                }
@@ -234,17 +287,28 @@ func sortFields(fields []*FieldInfo) {
                }
 
                if f1.IsPrimitive && f2.IsPrimitive {
-                       // Sort primitives by size (descending), then by type 
ID, then by name
+                       // Match reflection's boxed sorting logic exactly
+                       // First: handle compression types 
(INT32/INT64/VAR_INT32/VAR_INT64)
+                       compressI := f1.TypeID == "INT32" || f1.TypeID == 
"INT64" ||
+                               f1.TypeID == "VAR_INT32" || f1.TypeID == 
"VAR_INT64"
+                       compressJ := f2.TypeID == "INT32" || f2.TypeID == 
"INT64" ||
+                               f2.TypeID == "VAR_INT32" || f2.TypeID == 
"VAR_INT64"
+
+                       if compressI != compressJ {
+                               return !compressI && compressJ // non-compress 
comes first
+                       }
+
+                       // Then: by size (descending)
                        if f1.PrimitiveSize != f2.PrimitiveSize {
                                return f1.PrimitiveSize > f2.PrimitiveSize
                        }
-                       if f1.TypeID != f2.TypeID {
-                               return getTypeIDValue(f1.TypeID) < 
getTypeIDValue(f2.TypeID)
-                       }
+
+                       // Finally: by name (ascending)
                        return f1.SnakeName < f2.SnakeName
                }
 
-               // Sort non-primitives by type ID, then by name
+               // For non-primitives: STRING comes in final group, others in 
others group
+               // All sorted by type ID, then by name (matching reflection)
                if f1.TypeID != f2.TypeID {
                        return getTypeIDValue(f1.TypeID) < 
getTypeIDValue(f2.TypeID)
                }
@@ -253,27 +317,83 @@ func sortFields(fields []*FieldInfo) {
 }
 
 // computeStructHash computes a hash for struct schema compatibility
+// This implementation aligns with the reflection-based hash calculation
 func computeStructHash(s *StructInfo) int32 {
-       h := md5.New()
+       // Use the same iterative algorithm as reflection
+       var hash int32 = 17
 
-       // Write struct name
-       h.Write([]byte(s.Name))
-
-       // Write sorted field information
+       // Process fields in the same order as reflection
        for _, field := range s.Fields {
-               h.Write([]byte(field.SnakeName))
-               h.Write([]byte(field.TypeID))
-               // Add primitive size for better differentiation
-               if field.IsPrimitive {
-                       sizeBytes := make([]byte, 4)
-                       binary.LittleEndian.PutUint32(sizeBytes, 
uint32(field.PrimitiveSize))
-                       h.Write(sizeBytes)
+               id := getFieldHashID(field)
+
+               // Same algorithm as reflection: hash = hash * 31 + id
+               newHash := int64(hash)*31 + int64(id)
+
+               // Same overflow handling as reflection
+               const MaxInt32 = 2147483647
+               for newHash >= MaxInt32 {
+                       newHash /= 7
                }
+               hash = int32(newHash)
+       }
+
+       if hash == 0 {
+               // Same panic condition as reflection
+               panic(fmt.Errorf("hash for type %v is 0", s.Name))
+       }
+
+       return hash
+}
+
+// getFieldHashID computes the field ID for hash calculation, matching 
reflection logic exactly
+func getFieldHashID(field *FieldInfo) int32 {
+       // Map Go types to Fory TypeIds (exactly matching reflection)
+       var tid int16
+
+       switch field.TypeID {
+       case "BOOL":
+               tid = fory.BOOL
+       case "INT8":
+               tid = fory.INT8
+       case "INT16":
+               tid = fory.INT16
+       case "INT32":
+               tid = fory.INT32
+       case "INT64":
+               tid = fory.INT64
+       case "UINT8":
+               tid = fory.UINT8
+       case "UINT16":
+               tid = fory.UINT16
+       case "UINT32":
+               tid = fory.UINT32
+       case "UINT64":
+               tid = fory.UINT64
+       case "FLOAT32":
+               tid = fory.FLOAT
+       case "FLOAT64":
+               tid = fory.DOUBLE
+       case "STRING":
+               tid = fory.STRING
+       case "TIMESTAMP":
+               tid = fory.TIMESTAMP
+       case "LOCAL_DATE":
+               tid = fory.LOCAL_DATE
+       case "NAMED_STRUCT":
+               tid = fory.NAMED_STRUCT
+       case "LIST":
+               tid = fory.LIST
+       case "MAP":
+               tid = fory.MAP
+       default:
+               tid = 0 // Unknown type
        }
 
-       hashBytes := h.Sum(nil)
-       // Take first 4 bytes as int32
-       return int32(binary.LittleEndian.Uint32(hashBytes[:4]))
+       // Same logic as reflection: handle negative TypeIds
+       if tid < 0 {
+               return -int32(tid)
+       }
+       return int32(tid)
 }
 
 // getStructNames extracts struct names from StructInfo slice
diff --git a/go/fory/struct.go b/go/fory/struct.go
index 02b230279..77e5b8056 100644
--- a/go/fory/struct.go
+++ b/go/fory/struct.go
@@ -26,11 +26,12 @@ import (
 )
 
 type structSerializer struct {
-       typeTag    string
-       type_      reflect.Type
-       fieldsInfo structFieldsInfo
-       structHash int32
-       fieldDefs  []FieldDef // defs obtained during reading
+       typeTag         string
+       type_           reflect.Type
+       fieldsInfo      structFieldsInfo
+       structHash      int32
+       fieldDefs       []FieldDef // defs obtained during reading
+       codegenDelegate Serializer // Optional codegen serializer for 
performance (like Python's approach)
 }
 
 var UNKNOWN_TYPE_ID = int16(-1)
@@ -44,6 +45,12 @@ func (s *structSerializer) NeedWriteRef() bool {
 }
 
 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 {
+               return s.codegenDelegate.Write(f, buf, 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 {
@@ -78,6 +85,12 @@ func (s *structSerializer) Write(f *Fory, buf *ByteBuffer, 
value reflect.Value)
 }
 
 func (s *structSerializer) Read(f *Fory, buf *ByteBuffer, type_ reflect.Type, 
value reflect.Value) error {
+       // If we have a codegen delegate, use it for optimal performance
+       if s.codegenDelegate != nil {
+               return s.codegenDelegate.Read(f, buf, type_, value)
+       }
+
+       // Fall back to reflection-based deserialization
        // struct value may be a value type if it's not a pointer, so we don't 
invoke `refResolver.Reference` here,
        // but invoke it in `ptrToStructSerializer` instead.
        if value.Kind() == reflect.Ptr {
@@ -444,6 +457,7 @@ func (x structFieldsInfo) Swap(i, j int) { x[i], x[j] = 
x[j], x[i] }
 type ptrToStructSerializer struct {
        type_ reflect.Type
        structSerializer
+       codegenDelegate Serializer // Optional codegen serializer for 
performance (like Python's approach)
 }
 
 func (s *ptrToStructSerializer) TypeId() TypeId {
@@ -455,10 +469,22 @@ func (s *ptrToStructSerializer) NeedWriteRef() bool {
 }
 
 func (s *ptrToStructSerializer) Write(f *Fory, buf *ByteBuffer, value 
reflect.Value) error {
+       // If we have a codegen delegate, use it for optimal performance 
(Python-style approach)
+       if s.codegenDelegate != nil {
+               return s.codegenDelegate.Write(f, buf, value)
+       }
+
+       // Fall back to reflection-based serialization
        return s.structSerializer.Write(f, buf, value.Elem())
 }
 
 func (s *ptrToStructSerializer) Read(f *Fory, buf *ByteBuffer, type_ 
reflect.Type, value reflect.Value) error {
+       // If we have a codegen delegate, use it for optimal performance
+       if s.codegenDelegate != nil {
+               return s.codegenDelegate.Read(f, buf, type_, value)
+       }
+
+       // Fall back to reflection-based deserialization
        newValue := reflect.New(type_.Elem())
        value.Set(newValue)
        elem := newValue.Elem()
diff --git a/go/fory/tests/generator_test.go b/go/fory/tests/generator_test.go
index 452554783..f5d0d120b 100644
--- a/go/fory/tests/generator_test.go
+++ b/go/fory/tests/generator_test.go
@@ -33,12 +33,16 @@ func TestValidationDemo(t *testing.T) {
                A: 12345,         // int32
                B: "Hello Fory!", // string
                C: 98765,         // int64
+               D: 3.14159,       // float64
+               E: true,          // bool
        }
 
        // Validate original data structure
        assert.Equal(t, int32(12345), original.A, "Original A should be 12345")
        assert.Equal(t, "Hello Fory!", original.B, "Original B should be 'Hello 
Fory!'")
        assert.Equal(t, int64(98765), original.C, "Original C should be 98765")
+       assert.Equal(t, 3.14159, original.D, "Original D should be 3.14159")
+       assert.Equal(t, true, original.E, "Original E should be true")
 
        // 2. Serialize using generated code
        f := fory.NewFory(true)
@@ -53,11 +57,157 @@ func TestValidationDemo(t *testing.T) {
        require.NoError(t, err, "Deserialization should not fail")
        require.NotNil(t, result, "Deserialized result should not be nil")
 
-       // 4. Validate round-trip serialization
-       assert.Equal(t, original.A, result.A, "Field A should match after 
round-trip")
-       assert.Equal(t, original.B, result.B, "Field B should match after 
round-trip")
-       assert.Equal(t, original.C, result.C, "Field C should match after 
round-trip")
+       // 4. Assert that serializer is the generated serializer
+       validationSerializer := NewSerializerFor_ValidationDemo()
+       _, ok := validationSerializer.(ValidationDemo_ForyGenSerializer)
+       assert.True(t, ok, "Serializer should be the generated 
ValidationDemo_ForyGenSerializer")
+}
+
+func TestSliceDemo(t *testing.T) {
+       // 1. Create test instance with various slice types
+       original := &SliceDemo{
+               IntSlice:    []int32{10, 20, 30, 40, 50},
+               StringSlice: []string{"hello", "world", "fory", "slice"},
+               FloatSlice:  []float64{1.1, 2.2, 3.3, 4.4, 5.5},
+               BoolSlice:   []bool{true, false, true, false},
+       }
+
+       // Validate original data structure (quick sanity check)
+       assert.NotEmpty(t, original.IntSlice, "IntSlice should not be empty")
+       assert.NotEmpty(t, original.StringSlice, "StringSlice should not be 
empty")
+       assert.NotEmpty(t, original.FloatSlice, "FloatSlice should not be 
empty")
+       assert.NotEmpty(t, original.BoolSlice, "BoolSlice should not be empty")
+
+       // 2. Serialize using generated code
+       f := fory.NewFory(true)
+       data, err := f.Marshal(original)
+       require.NoError(t, err, "Serialization should not fail")
+       require.NotEmpty(t, data, "Serialized data should not be empty")
+       assert.Greater(t, len(data), 0, "Serialized data should have positive 
length")
+
+       // 3. Deserialize using generated code
+       var result *SliceDemo
+       err = f.Unmarshal(data, &result)
+       require.NoError(t, err, "Deserialization should not fail")
+       require.NotNil(t, result, "Deserialized result should not be nil")
+
+       // 4. Assert that serializer is the generated serializer
+       sliceSerializer := NewSerializerFor_SliceDemo()
+       _, ok := sliceSerializer.(SliceDemo_ForyGenSerializer)
+       assert.True(t, ok, "Serializer should be the generated 
SliceDemo_ForyGenSerializer")
+}
+
+func TestDynamicSliceDemo(t *testing.T) {
+       // 1. Create test instance with various interface{} types
+       original := &DynamicSliceDemo{
+               DynamicSlice: []interface{}{
+                       int32(42),
+                       "hello",
+                       float64(3.14),
+                       true,
+                       int64(12345),
+               },
+       }
+
+       // Validate original data structure (quick sanity check)
+       assert.Equal(t, 5, len(original.DynamicSlice), "DynamicSlice should 
have 5 elements")
+       assert.Equal(t, int32(42), original.DynamicSlice[0], "First element 
should be int32(42)")
+       assert.Equal(t, "hello", original.DynamicSlice[1], "Second element 
should be 'hello'")
+       assert.Equal(t, float64(3.14), original.DynamicSlice[2], "Third element 
should be float64(3.14)")
+       assert.Equal(t, true, original.DynamicSlice[3], "Fourth element should 
be true")
+       assert.Equal(t, int64(12345), original.DynamicSlice[4], "Fifth element 
should be int64(12345)")
+
+       // 2. Serialize using generated code
+       f := fory.NewFory(true)
+       data, err := f.Marshal(original)
+       require.NoError(t, err, "Serialization should not fail")
+       require.NotEmpty(t, data, "Serialized data should not be empty")
+       assert.Greater(t, len(data), 0, "Serialized data should have positive 
length")
+
+       // 3. Deserialize using generated code
+       var result *DynamicSliceDemo
+       err = f.Unmarshal(data, &result)
+       require.NoError(t, err, "Deserialization should not fail")
+       require.NotNil(t, result, "Deserialized result should not be nil")
+
+       // 4. Assert that serializer is the generated serializer
+       dynamicSerializer := NewSerializerFor_DynamicSliceDemo()
+       _, ok := dynamicSerializer.(DynamicSliceDemo_ForyGenSerializer)
+       assert.True(t, ok, "Serializer should be the generated 
DynamicSliceDemo_ForyGenSerializer")
+}
+
+func TestDynamicSliceDemoWithNilAndEmpty(t *testing.T) {
+       // Test with nil and empty dynamic slices
+       original := &DynamicSliceDemo{
+               DynamicSlice: nil, // nil slice
+       }
+
+       // Serialize using generated code
+       f := fory.NewFory(true)
+       data, err := f.Marshal(original)
+       require.NoError(t, err, "Serialization should not fail")
+       require.NotEmpty(t, data, "Serialized data should not be empty")
+
+       // Deserialize using generated code
+       var result *DynamicSliceDemo
+       err = f.Unmarshal(data, &result)
+       require.NoError(t, err, "Deserialization should not fail")
+       require.NotNil(t, result, "Deserialized result should not be nil")
+
+       // Validate nil slice handling
+       assert.Nil(t, result.DynamicSlice, "DynamicSlice should be nil after 
round-trip")
+
+       // Test with empty slice
+       originalEmpty := &DynamicSliceDemo{
+               DynamicSlice: []interface{}{}, // empty slice
+       }
+
+       dataEmpty, err := f.Marshal(originalEmpty)
+       require.NoError(t, err, "Empty slice serialization should not fail")
+
+       var resultEmpty *DynamicSliceDemo
+       err = f.Unmarshal(dataEmpty, &resultEmpty)
+       require.NoError(t, err, "Empty slice deserialization should not fail")
+       require.NotNil(t, resultEmpty, "Deserialized result should not be nil")
+
+       // Empty slice should remain empty (or become nil, depending on 
reflection behavior)
+       assert.Equal(t, 0, len(resultEmpty.DynamicSlice), "DynamicSlice should 
be empty after round-trip")
+}
+
+// TestMapDemo tests basic map serialization and deserialization (including 
nil maps)
+func TestMapDemo(t *testing.T) {
+       // Create test instance with various map types (including nil)
+       instance := &MapDemo{
+               StringMap: map[string]string{
+                       "key1": "value1",
+                       "key2": "value2",
+               },
+               IntMap: map[int]int{
+                       1: 100,
+                       2: 200,
+                       3: 300,
+               },
+               MixedMap: nil, // Test nil map handling
+       }
+
+       // Serialize with codegen
+       f := fory.NewFory(true)
+       data, err := f.Marshal(instance)
+       require.NoError(t, err, "Serialization failed")
+
+       // Deserialize back
+       var result MapDemo
+       err = f.Unmarshal(data, &result)
+       require.NoError(t, err, "Deserialization failed")
+
+       // Verify using generated serializer
+       serializer := NewSerializerFor_MapDemo()
+       assert.NotNil(t, serializer, "Generated serializer should exist")
 
-       // 5. Validate data integrity
-       assert.EqualValues(t, original, result, "Complete struct should match 
after round-trip")
+       // Verify map contents
+       assert.EqualValues(t, instance.StringMap, result.StringMap, "StringMap 
mismatch")
+       assert.EqualValues(t, instance.IntMap, result.IntMap, "IntMap mismatch")
+       // MixedMap was nil, should become empty after deserialization
+       assert.NotNil(t, result.MixedMap, "Expected non-nil MixedMap after 
deserialization")
+       assert.Empty(t, result.MixedMap, "Expected empty MixedMap since 
original was nil")
 }
diff --git a/go/fory/tests/generator_xlang_test.go 
b/go/fory/tests/generator_xlang_test.go
new file mode 100644
index 000000000..3bc49711c
--- /dev/null
+++ b/go/fory/tests/generator_xlang_test.go
@@ -0,0 +1,291 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package fory
+
+import (
+       "reflect"
+       "testing"
+
+       forygo "github.com/apache/fory/go/fory"
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/require"
+)
+
+// TestActualCodegenName - Analyze actual type names used by codegen
+func TestActualCodegenName(t *testing.T) {
+       // From source code analysis:
+       // RegisterSerializerFactory calculates: typeTag := pkgPath + "." + 
typeName
+
+       validationDemoType := reflect.TypeOf(ValidationDemo{})
+       pkgPath := validationDemoType.PkgPath()
+       typeName := validationDemoType.Name()
+       expectedTypeTag := pkgPath + "." + typeName
+
+       // Create test data
+       codegenInstance := &ValidationDemo{
+               A: 100,
+               B: "test_data",
+               C: 200,
+               D: 3.14159,
+               E: true,
+       }
+
+       type ReflectStruct struct {
+               A int32
+               B string
+               C int64
+               D float64
+               E bool
+       }
+
+       reflectInstance := &ReflectStruct{
+               A: 100,
+               B: "test_data",
+               C: 200,
+               D: 3.14159,
+               E: true,
+       }
+
+       // Codegen mode (automatically uses full name)
+       foryForCodegen := forygo.NewFory(true)
+
+       // Reflect mode (register with full name)
+       foryForReflect := forygo.NewFory(true)
+       err := foryForReflect.RegisterTagType(expectedTypeTag, ReflectStruct{})
+       require.NoError(t, err, "Should be able to register ReflectStruct with 
full name")
+
+       // Serialization test
+       codegenData, err := foryForCodegen.Marshal(codegenInstance)
+       require.NoError(t, err, "Codegen serialization should not fail")
+
+       reflectData, err := foryForReflect.Marshal(reflectInstance)
+       require.NoError(t, err, "Reflect serialization should not fail")
+
+       // Use reflect to deserialize codegen data
+       var reflectResult *ReflectStruct
+       err = foryForReflect.Unmarshal(codegenData, &reflectResult)
+       require.NoError(t, err, "Reflect should be able to deserialize codegen 
data")
+       require.NotNil(t, reflectResult, "Reflect result should not be nil")
+
+       // Verify content matches original
+       assert.EqualValues(t, codegenInstance, reflectResult, "Reflect 
deserialized data should match original")
+
+       // Use codegen to deserialize reflect data
+       var codegenResult *ValidationDemo
+       err = foryForCodegen.Unmarshal(reflectData, &codegenResult)
+       require.NoError(t, err, "Codegen should be able to deserialize reflect 
data")
+       require.NotNil(t, codegenResult, "Codegen result should not be nil")
+
+       // Verify content matches original
+       assert.EqualValues(t, reflectInstance, codegenResult, "Codegen 
deserialized data should match original")
+}
+
+// TestSliceDemoXlang - Test cross-language compatibility of SliceDemo
+func TestSliceDemoXlang(t *testing.T) {
+       // Get SliceDemo type information
+       sliceDemoType := reflect.TypeOf(SliceDemo{})
+       pkgPath := sliceDemoType.PkgPath()
+       typeName := sliceDemoType.Name()
+       expectedTypeTag := pkgPath + "." + typeName
+
+       // Create test data
+       codegenInstance := &SliceDemo{
+               IntSlice:    []int32{1, 2, 3, 4, 5},
+               StringSlice: []string{"hello", "world", "fory"},
+               FloatSlice:  []float64{1.1, 2.2, 3.3},
+               BoolSlice:   []bool{true, false, true},
+       }
+
+       // Define equivalent struct using reflection
+       type ReflectSliceStruct struct {
+               IntSlice    []int32
+               StringSlice []string
+               FloatSlice  []float64
+               BoolSlice   []bool
+       }
+
+       reflectInstance := &ReflectSliceStruct{
+               IntSlice:    []int32{1, 2, 3, 4, 5},
+               StringSlice: []string{"hello", "world", "fory"},
+               FloatSlice:  []float64{1.1, 2.2, 3.3},
+               BoolSlice:   []bool{true, false, true},
+       }
+
+       // Codegen mode - enable reference tracking
+       foryForCodegen := forygo.NewFory(true)
+
+       // Reflect mode - enable reference tracking
+       foryForReflect := forygo.NewFory(true)
+       err := foryForReflect.RegisterTagType(expectedTypeTag, 
ReflectSliceStruct{})
+       require.NoError(t, err, "Should be able to register ReflectSliceStruct 
with full name")
+
+       // Serialization test
+       codegenData, err := foryForCodegen.Marshal(codegenInstance)
+       require.NoError(t, err, "Codegen serialization should not fail")
+
+       reflectData, err := foryForReflect.Marshal(reflectInstance)
+       require.NoError(t, err, "Reflect serialization should not fail")
+
+       // Verify cross serialization
+
+       // Use reflect to deserialize codegen data
+       var reflectResult *ReflectSliceStruct
+       err = foryForReflect.Unmarshal(codegenData, &reflectResult)
+       require.NoError(t, err, "Reflect should be able to deserialize codegen 
data")
+       require.NotNil(t, reflectResult, "Reflect result should not be nil")
+
+       // Verify content matches original
+       assert.EqualValues(t, codegenInstance.IntSlice, reflectResult.IntSlice, 
"IntSlice mismatch")
+       assert.EqualValues(t, codegenInstance.StringSlice, 
reflectResult.StringSlice, "StringSlice mismatch")
+       assert.EqualValues(t, codegenInstance.FloatSlice, 
reflectResult.FloatSlice, "FloatSlice mismatch")
+       assert.EqualValues(t, codegenInstance.BoolSlice, 
reflectResult.BoolSlice, "BoolSlice mismatch")
+
+       // Use codegen to deserialize reflect data
+       var codegenResult *SliceDemo
+       err = foryForCodegen.Unmarshal(reflectData, &codegenResult)
+       require.NoError(t, err, "Codegen should be able to deserialize reflect 
data")
+       require.NotNil(t, codegenResult, "Codegen result should not be nil")
+
+       // Verify content matches original
+       assert.EqualValues(t, reflectInstance.IntSlice, codegenResult.IntSlice, 
"IntSlice mismatch")
+       assert.EqualValues(t, reflectInstance.StringSlice, 
codegenResult.StringSlice, "StringSlice mismatch")
+       assert.EqualValues(t, reflectInstance.FloatSlice, 
codegenResult.FloatSlice, "FloatSlice mismatch")
+       assert.EqualValues(t, reflectInstance.BoolSlice, 
codegenResult.BoolSlice, "BoolSlice mismatch")
+
+}
+
+// TestDynamicSliceDemoXlang - Test cross-language compatibility of 
DynamicSliceDemo
+func TestDynamicSliceDemoXlang(t *testing.T) {
+       // Get DynamicSliceDemo type information
+       dynamicSliceType := reflect.TypeOf(DynamicSliceDemo{})
+       pkgPath := dynamicSliceType.PkgPath()
+       typeName := dynamicSliceType.Name()
+       expectedTypeTag := pkgPath + "." + typeName
+
+       // Create test data with simpler types to avoid reflection issues
+       codegenInstance := &DynamicSliceDemo{
+               DynamicSlice: []interface{}{
+                       "first",
+                       200, // Testing mixed types in dynamic slice
+                       "third",
+               },
+       }
+
+       // Define equivalent struct using reflection
+       type ReflectDynamicStruct struct {
+               DynamicSlice []interface{} `json:"dynamic_slice"`
+       }
+
+       reflectInstance := &ReflectDynamicStruct{
+               DynamicSlice: []interface{}{
+                       "first",
+                       200, // Testing mixed types in dynamic slice
+                       "third",
+               },
+       }
+
+       // Codegen mode - enable reference tracking
+       foryForCodegen := forygo.NewFory(true)
+
+       // Reflect mode - enable reference tracking
+       foryForReflect := forygo.NewFory(true)
+       err := foryForReflect.RegisterTagType(expectedTypeTag, 
ReflectDynamicStruct{})
+       require.NoError(t, err, "Should be able to register 
ReflectDynamicStruct with full name")
+
+       // Serialization test
+       codegenData, err := foryForCodegen.Marshal(codegenInstance)
+       require.NoError(t, err, "Codegen serialization should not fail")
+
+       reflectData, err := foryForReflect.Marshal(reflectInstance)
+       require.NoError(t, err, "Reflect serialization should not fail")
+
+       // Test cross deserialization - reflect deserializes codegen data
+       var reflectResult *ReflectDynamicStruct
+       err = foryForReflect.Unmarshal(codegenData, &reflectResult)
+       require.NoError(t, err, "Reflect should be able to deserialize codegen 
data")
+       require.NotNil(t, reflectResult, "Reflect result should not be nil")
+
+       // Verify content matches original
+       assert.EqualValues(t, codegenInstance.DynamicSlice, 
reflectResult.DynamicSlice, "DynamicSlice mismatch")
+
+       // Test opposite direction - codegen deserializes reflect data
+       var codegenResult *DynamicSliceDemo
+       err = foryForCodegen.Unmarshal(reflectData, &codegenResult)
+       require.NoError(t, err, "Codegen should be able to deserialize reflect 
data")
+       require.NotNil(t, codegenResult, "Codegen result should not be nil")
+
+       // Verify content matches original
+       assert.EqualValues(t, reflectInstance.DynamicSlice, 
codegenResult.DynamicSlice, "DynamicSlice mismatch")
+}
+
+// TestMapDemoXlang tests cross-language compatibility for map types
+func TestMapDemoXlang(t *testing.T) {
+       // Create test instance with same data for both codegen and reflection
+       codegenInstance := &MapDemo{
+               StringMap: map[string]string{
+                       "key1": "value1",
+                       "key2": "value2",
+               },
+               IntMap: map[int]int{
+                       1: 100,
+                       2: 200,
+                       3: 300,
+               },
+               MixedMap: map[string]int{
+                       "one":   1,
+                       "two":   2,
+                       "three": 3,
+               },
+       }
+
+       // Use same instance for reflection (simplified test)
+       reflectInstance := codegenInstance
+
+       // Create Fory instances with reference tracking enabled
+       foryForCodegen := forygo.NewFory(true)
+       foryForReflect := forygo.NewFory(true)
+
+       // No need to register MapDemo - it has codegen serializer automatically
+
+       // Serialize both instances
+       codegenData, err := foryForCodegen.Marshal(codegenInstance)
+       require.NoError(t, err, "Codegen serialization should not fail")
+
+       reflectData, err := foryForReflect.Marshal(reflectInstance)
+       require.NoError(t, err, "Reflect serialization should not fail")
+
+       // Test cross deserialization - reflect deserializes codegen data
+       var reflectResult MapDemo
+       err = foryForReflect.Unmarshal(codegenData, &reflectResult)
+       require.NoError(t, err, "Reflect should be able to deserialize codegen 
data")
+
+       // Verify content matches original
+       assert.EqualValues(t, codegenInstance.StringMap, 
reflectResult.StringMap, "StringMap mismatch")
+       assert.EqualValues(t, codegenInstance.IntMap, reflectResult.IntMap, 
"IntMap mismatch")
+       assert.EqualValues(t, codegenInstance.MixedMap, reflectResult.MixedMap, 
"MixedMap mismatch")
+
+       // Test opposite direction - codegen deserializes reflect data
+       var codegenResult MapDemo
+       err = foryForCodegen.Unmarshal(reflectData, &codegenResult)
+       require.NoError(t, err, "Codegen should be able to deserialize reflect 
data")
+
+       // Verify content matches original
+       assert.EqualValues(t, reflectInstance.StringMap, 
codegenResult.StringMap, "StringMap mismatch")
+       assert.EqualValues(t, reflectInstance.IntMap, codegenResult.IntMap, 
"IntMap mismatch")
+       assert.EqualValues(t, reflectInstance.MixedMap, codegenResult.MixedMap, 
"MixedMap mismatch")
+}
diff --git a/go/fory/tests/structs.go b/go/fory/tests/structs.go
index 170c255e4..37399e064 100644
--- a/go/fory/tests/structs.go
+++ b/go/fory/tests/structs.go
@@ -18,11 +18,38 @@
 package fory
 
 // ValidationDemo is a simple struct for testing code generation
-// Contains only basic types since PR1 only supports basic types
+// Contains various basic types to validate comprehensive type support
 
 // fory:gen
 type ValidationDemo struct {
-       A int32  `json:"a"` // int32 field
-       B string `json:"b"` // string field
-       C int64  `json:"c"` // int64 field (instead of array, as arrays are not 
supported yet)
+       A int32   // int32 field
+       B string  // string field
+       C int64   // int64 field
+       D float64 // float64 field
+       E bool    // bool field
+}
+
+// SliceDemo is a struct for testing slice serialization
+// Contains various slice types
+
+// fory:gen
+type SliceDemo struct {
+       IntSlice    []int32   // slice of int32
+       StringSlice []string  // slice of string
+       FloatSlice  []float64 // slice of float64
+       BoolSlice   []bool    // slice of bool
+}
+
+// DynamicSliceDemo is a struct for testing dynamic slice serialization
+// fory:gen
+type DynamicSliceDemo struct {
+       DynamicSlice []interface{} // slice of interface{}
+}
+
+// MapDemo demonstrates map field support
+// fory:gen
+type MapDemo struct {
+       StringMap map[string]string // map[string]string
+       IntMap    map[int]int       // map[int]int
+       MixedMap  map[string]int    // map[string]int
 }
diff --git a/go/fory/type.go b/go/fory/type.go
index 60587af32..7d0508af7 100644
--- a/go/fory/type.go
+++ b/go/fory/type.go
@@ -372,38 +372,51 @@ func newTypeResolver(fory *Fory) *typeResolver {
        }
        r.initialize()
 
-       // Register generated serializers from factories
+       // Register generated serializers from factories with complete type 
information
        generatedSerializerFactories.mu.RLock()
        for type_, factory := range generatedSerializerFactories.factories {
-               serializer := factory()
-
-               // Use full registration process for generated types
+               codegenSerializer := factory()
                pkgPath := type_.PkgPath()
                typeName := type_.Name()
+               typeTag := pkgPath + "." + typeName
 
-               // Register value type
-               _, err := r.registerType(type_, int32(serializer.TypeId()), 
pkgPath, typeName, serializer, true)
-               if err != nil {
-                       fmt.Errorf("failed to register generated type %v: %v", 
type_, err)
+               // Create structSerializer with codegen delegate (Python-style)
+               structSer := &structSerializer{
+                       typeTag:         typeTag,
+                       type_:           type_,
+                       codegenDelegate: codegenSerializer, // Delegate to 
codegen for performance
                }
-
-               // Also register pointer type in serializers map (without full 
registration to avoid typeId conflict)
+               // Create ptrToStructSerializer with codegen delegate 
(Python-style)
                ptrType := reflect.PtrTo(type_)
-               r.typeToSerializers[ptrType] = serializer
-
-               // Create TypeInfo for pointer type and add to cache
-               if typeInfo, exists := r.typesInfo[type_]; exists {
-                       ptrTypeInfo := TypeInfo{
-                               Type:         ptrType,
-                               TypeID:       -typeInfo.TypeID, // Use negative 
ID for pointer type
-                               Serializer:   serializer,
-                               PkgPathBytes: typeInfo.PkgPathBytes,
-                               NameBytes:    typeInfo.NameBytes,
-                               IsDynamic:    true,
-                               hashValue:    calcTypeHash(ptrType),
-                       }
-                       r.typesInfo[ptrType] = ptrTypeInfo
+               ptrStructSer := &ptrToStructSerializer{
+                       type_:            ptrType,
+                       structSerializer: *structSer,
+                       codegenDelegate:  codegenSerializer, // Delegate to 
codegen for performance
                }
+
+               // 1. Basic type mappings (same as reflection)
+               r.typeToSerializers[type_] = structSer      // Value type -> 
structSerializer with codegen
+               r.typeToSerializers[ptrType] = ptrStructSer // Pointer type -> 
ptrToStructSerializer with codegen
+
+               // 2. Cross-language critical mapping (same as reflection)
+               r.typeTagToSerializers[typeTag] = ptrStructSer // "pkg.Type" -> 
ptrToStructSerializer
+
+               // 3. Register complete type information (critical for proper 
serialization)
+               _, err := r.registerType(type_, 
int32(codegenSerializer.TypeId()), pkgPath, typeName, structSer, false)
+               if err != nil {
+                       panic(fmt.Errorf("failed to register codegen type %s: 
%v", typeTag, err))
+               }
+               // 4. Register pointer type information
+               _, err = r.registerType(ptrType, 
-int32(codegenSerializer.TypeId()), pkgPath, typeName, ptrStructSer, false)
+               if err != nil {
+                       panic(fmt.Errorf("failed to register codegen pointer 
type %s: %v", typeTag, err))
+               }
+
+               // 5. Type info mappings (same as reflection) - these are 
redundant if registerType is called
+               r.typeToTypeInfo[type_] = "@" + typeTag    // Type -> 
"@pkg.Type"
+               r.typeToTypeInfo[ptrType] = "*@" + typeTag // *Type -> 
"*@pkg.Type"
+               r.typeInfoToType["@"+typeTag] = type_      // "@pkg.Type" -> 
Type
+               r.typeInfoToType["*@"+typeTag] = ptrType   // "*@pkg.Type" -> 
*Type
        }
        generatedSerializerFactories.mu.RUnlock()
 
@@ -532,7 +545,7 @@ func (r *typeResolver) getTypeInfo(value reflect.Value, 
create bool) (TypeInfo,
                if info.Serializer == nil {
                        /*
                           Lazy initialize serializer if not created yet
-                          mapInStruct equals false because this path isn't 
taken when extracting field info from structs;
+                          mapInStruct equals false because this path isn’t 
taken when extracting field info from structs;
                           for all other map cases, it remains false
                        */
                        serializer, err := r.createSerializer(value.Type(), 
false)
@@ -554,7 +567,6 @@ func (r *typeResolver) getTypeInfo(value reflect.Value, 
create bool) (TypeInfo,
                value = value.Elem()
        }
        type_ := value.Type()
-
        // Get package path and type name for registration
        var typeName string
        var pkgPath string


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

Reply via email to