Fory is a blazingly fast multi-language serialization framework powered by just-in-time compilation and zero-copy.
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.
Fory Go supports the following types for both reflection-based serialization and code generation:
boolint8, int16, int32, int64, intuint8 (byte)float32, float64string[]bool, []int16, []int32, []int64[]float32, []float64[]string[]interface{} (dynamic slice)map[string]string, map[int]int, map[string]intThis repository includes an optional ahead-of-time (AOT) code generator for Fory. The runtime reflection-based path continues to work; codegen exists to provide additional performance, type safety and zero-reflection overhead for hot paths. You can adopt it incrementally, per package or per file.
Note: Code generation is not mandatory. If you prefer simple workflows, you can keep using the reflection-based API.
The generator binary is fory.
go install github.com/apache/fory/go/fory/cmd/fory@latest
# Inside a module-enabled environment GO111MODULE=on go get -u github.com/apache/fory/go/fory/cmd/fory # Or clone the repo and install from source git clone https://github.com/apache/fory.git cd fory/go/fory go install ./cmd/fory
Ensure $GOBIN or $GOPATH/bin is on your PATH so that fory is discoverable by go generate.
//fory:generate, and add a go:generate directive. File-based generation is recommended.package yourpkg //fory:generate type User struct { ID int64 `json:"id"` Name string `json:"name"` } //go:generate fory -file structs.go
Then run:
go generate
The generator will create structs_fory_gen.go next to your source file and register serializers in init().
fory -pkg ./models -type "User,Order"
go generateRe-run generation whenever any of the following change for generated structs:
//fory:generateFory adds a compile-time guard in generated files to detect stale code. If you forget to re-generate, your build will fail with a clear message. The generator also includes a smart auto-retry: when invoked via go generate, it detects this situation, removes the stale generated file, and retries automatically. You can force this behavior manually with:
fory --force -file structs.go
Below is a minimal illustration. Actual output includes strongly-typed serializers, interface-compatible methods, registration, and a compile-time snapshot of your struct.
// Code generated by fory. DO NOT EDIT. package yourpkg // Snapshot of User's underlying type at generation time. type _User_expected struct { ID int64 Name string } // Compile-time check: fails if User no longer matches the snapshot. // If this fails, run: go generate var _ = func(x User) { _ = _User_expected(x) } type User_ForyGenSerializer struct{} func (User_ForyGenSerializer) WriteTyped(f *fory.Fory, buf *fory.ByteBuffer, v *User) error { // write fields in a stable order buf.WriteInt64(v.ID) fory.WriteString(buf, v.Name) return nil } func (User_ForyGenSerializer) ReadTyped(f *fory.Fory, buf *fory.ByteBuffer, v *User) error { v.ID = buf.ReadInt64() v.Name = fory.ReadString(buf) return nil }
Both models are supported; choose based on your workflow:
Check in generated code (recommended for libraries)
Do not check in; generate in CI/release pipeline (recommended for apps)
go generate ./...fory --force -file <file.go> for targeted regenerationRegardless of your choice, the compile-time guard ensures that stale code is noticed early. If a build fails due to the guard in a local environment, run:
go generate # If needed fory --force -file <your file>
Fory Go supports several configuration options through the functional options pattern:
Compatible mode enables meta information sharing, which allows for schema evolution:
// Enable compatible mode with meta share fory := NewForyWithOptions(WithCompatible(true))
Enable reference tracking:
fory := NewForyWithOptions(WithRefTracking(true))
You can combine multiple options:
fory := NewForyWithOptions(
WithCompatible(true),
WithRefTracking(true),
)
Choose the right registration approach for your use case:
// Register using an explicit namespace and type name pair. func (f *Fory) RegisterByNamespace(User{}, "example", "user") error // Register using a name func (f *Fory) RegisterNamedType(User{}, "example.user") error // Register using a pre-assigned numeric type identifier. func (f *Fory) Register(User{}, 101) error
cd go/fory go test -v ./... go test -v fory_xlang_test.go
cd go/fory gofmt -s -w .
When using Go's gofmt -s -w . command on Windows, ensure your source files use Unix-style line endings (LF) instead of Windows-style (CRLF). Go tools expect LF by default, and mismatched line endings may cause unexpected behavior or unnecessary changes in version control.
Before committing, you can use git config core.autocrlf input to take effect on future commits.