title: Configuration sidebar_position: 10 id: configuration license: | 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
Fory Go uses a functional options pattern for configuration. This allows you to customize serialization behavior while maintaining sensible defaults.
import "github.com/apache/fory/go/fory"
f := fory.New()
Default settings:
| Option | Default | Description |
|---|---|---|
| TrackRef | false | Reference tracking disabled |
| MaxDepth | 20 | Maximum nesting depth |
| IsXlang | false | Cross-language mode disabled |
| Compatible | false | Schema evolution mode disabled |
f := fory.New(
fory.WithTrackRef(true),
fory.WithCompatible(true),
fory.WithMaxDepth(10),
)
Enable reference tracking to handle circular references and shared objects:
f := fory.New(fory.WithTrackRef(true))
When enabled:
fory:"ref" tags take effectWhen disabled (default):
fory:"ref" tags are ignoredUse reference tracking when:
See References for details.
Enable compatible mode for schema evolution:
f := fory.New(fory.WithCompatible(true))
When enabled:
When disabled (default):
See Schema Evolution for details.
Set the maximum nesting depth to prevent stack overflow:
f := fory.New(fory.WithMaxDepth(30))
Enable cross-language serialization mode:
f := fory.New(fory.WithXlang(true))
When enabled:
When disabled (default):
The default Fory instance is NOT thread-safe. For concurrent use, use the thread-safe wrapper:
import "github.com/apache/fory/go/fory/threadsafe" // Create thread-safe Fory with same options f := threadsafe.New( fory.WithTrackRef(true), fory.WithCompatible(true), ) // Safe for concurrent use from multiple goroutines go func() { data, _ := f.Serialize(value1) // data is already copied, safe to use after return }() go func() { data, _ := f.Serialize(value2) }()
The thread-safe wrapper:
sync.Pool internally for efficient instance reusefory.New()For convenience, the threadsafe package provides global functions:
import "github.com/apache/fory/go/fory/threadsafe" // Uses a global thread-safe instance with default configuration data, err := threadsafe.Marshal(&myValue) err = threadsafe.Unmarshal(data, &result)
See Thread Safety for details.
The default Fory instance reuses its internal buffer:
f := fory.New() data1, _ := f.Serialize(value1) // WARNING: data1 becomes invalid after next Serialize call! data2, _ := f.Serialize(value2) // data1 now points to invalid memory // To keep the data, copy it: safeCopy := make([]byte, len(data1)) copy(safeCopy, data1)
The thread-safe wrapper automatically copies data, so this is not a concern:
f := threadsafe.New() data1, _ := f.Serialize(value1) data2, _ := f.Serialize(value2) // Both data1 and data2 are valid
For high-throughput scenarios, you can manage buffers manually:
f := fory.New() buf := fory.NewByteBuffer(nil) // Serialize to existing buffer err := f.SerializeTo(buf, value) // Get serialized data data := buf.GetByteSlice(0, buf.WriterIndex()) // Process data... // Reset for next use buf.Reset()
For simple structs without circular references:
f := fory.New()
type Config struct {
Host string
Port int32
}
f.RegisterStruct(Config{}, 1)
data, _ := f.Serialize(&Config{Host: "localhost", Port: 8080})
For data with circular references:
f := fory.New(fory.WithTrackRef(true)) type Node struct { Value int32 Next *Node `fory:"ref"` } f.RegisterStruct(Node{}, 1) n1 := &Node{Value: 1} n2 := &Node{Value: 2} n1.Next = n2 n2.Next = n1 // Circular reference data, _ := f.Serialize(n1)
For data that may evolve over time:
// V1: original struct type UserV1 struct { ID int64 Name string } // V2: added Email field type UserV2 struct { ID int64 Name string Email string // New field } // Serialize with V1 f1 := fory.New(fory.WithCompatible(true)) f1.RegisterStruct(UserV1{}, 1) data, _ := f1.Serialize(&UserV1{ID: 1, Name: "Alice"}) // Deserialize into V2 - Email will have zero value f2 := fory.New(fory.WithCompatible(true)) f2.RegisterStruct(UserV2{}, 1) var user UserV2 f2.Deserialize(data, &user)
For concurrent high-throughput scenarios:
type Request struct { ID int64 Payload string } f := threadsafe.New( fory.WithMaxDepth(30), ) f.RegisterStruct(Request{}, 1) // Process requests concurrently for req := range requests { go func(r Request) { data, _ := f.Serialize(&r) sendResponse(data) }(req) }
Reuse Fory instances: Creating a Fory instance involves initialization overhead. Create once and reuse.
Use thread-safe wrapper for concurrency: Never share a non-thread-safe Fory instance across goroutines.
Enable reference tracking only when needed: It adds overhead for tracking object identity.
Copy serialized data if keeping it: With the default Fory, the returned byte slice is invalidated on the next operation.
Set appropriate max depth: Increase for deeply nested structures, but be aware of memory usage.
Use compatible mode for evolving schemas: Enable when struct definitions may change between service versions.