thriftgo is an Apache Thrift IDL compiler written in Go. It generates Go source code from .thrift files and extends the standard compiler with a plugin system for custom code generation.
- Parses Thrift IDL files and generates Go code with extensive customization options.
- Use it when you need to generate Go types, serialization code, or RPC interfaces from
.thriftdefinitions, especially in the CloudWeGo ecosystem.
The generated Go code depends on the Apache Thrift Go runtime library. Thriftgo targets github.com/apache/thrift v0.13.0 only. Version 0.14.0 introduced breaking changes to core interfaces (TProtocol, TTransport, TProcessor) by adding context.Context parameters, making it incompatible with code generated by thriftgo.
To avoid the Apache Thrift runtime dependency entirely, use no_default_serdes and no_processor together — this generates plain Go structs without Read/Write methods or processor/client code. Alternatively, use thrift_import_path=<path> to redirect the import to a fork or vendored copy.
Prerequisites: Go 1.18 or later. Ensure $GOPATH/bin (default: ~/go/bin) is in your PATH so the installed binary is accessible.
Install via go install (recommended):
go install github.com/cloudwego/thriftgo@latestInstall from source:
go install github.com/cloudwego/thriftgo@latestVerify installation:
thriftgo --versionGenerate Go code from a Thrift IDL file:
thriftgo -g go example.thriftOutput is written to ./gen-go/<namespace>/.
thriftgo [options] <file.thrift>
| Flag | Short | Type | Default | Description |
|---|---|---|---|---|
--version |
bool | false | Print the compiler version and exit. | |
--help |
-h |
bool | false | Print help message and exit. |
--gen |
-g |
string | Target language and options (required). Repeatable for multiple backends. Form: language[:key1=val1[,key2[,key3=val3]]].Available backends: go, fastgo (experimental). |
|
--out |
-o |
string | ./gen-<lang> |
Output directory. Supports {namespace} and {namespaceUnderscore} placeholders. |
--include |
-i |
string | Add a search path for includes. Repeatable. | |
--recurse |
-r |
bool | false | Recursively generate code for all included files. |
--plugin |
-p |
string | Invoke an external plugin. Repeatable. Form: plugin[=path][:key1=val1[,...]]. |
|
--verbose |
-v |
bool | false | Output detailed info logs to stderr. |
--quiet |
-q |
bool | false | Suppress all warnings and info logs. |
--check-keywords |
bool | true | Parsed but currently unused. Intended to warn if identifiers use keywords from common languages. |
|
--plugin-time-limit |
duration | 1m |
Execution time limit for plugins. 0 means no limit. |
--quiet suppresses all output including warnings. --verbose adds info-level logs. When both are set, --quiet wins.
The fastgo backend generates additional k-<file>.go files containing high-performance FastRead, FastWrite, and BLength methods for structs, unions, and exceptions. It runs the standard go backend first and then appends these files.
thriftgo -g fastgo example.thriftfastgo accepts the same options as the go backend. Do not combine -g go and -g fastgo — fastgo already runs the go backend internally, so using both would produce duplicate files.
Options are passed as a comma-separated list after go:. Combine multiple options with commas:
thriftgo -g go:naming_style=golint,gen_setter,template=slim example.thriftBoolean options accept true, false, or empty (empty means true).
| Option | Default | Description |
|---|---|---|
thrift_import_path=<path> |
Override the thrift runtime import path. Default: github.com/apache/thrift/lib/go/thrift. |
|
use_package=<path>=<repl> |
Replace an import path. Form: path=replacement. |
|
naming_style=<style> |
thriftgo |
Identifier naming style: golint, apache, or thriftgo. |
ignore_initialisms |
false | Disable spelling correction of initialisms (e.g. URL). |
package_prefix=<prefix> |
Prepend a package prefix to all generated import paths. | |
template=<name> |
Use an alternative code template: slim or raw_struct. |
|
json_enum_as_text |
false | Generate MarshalText and UnmarshalText for enum values. |
enum_marshal |
false | Generate MarshalText for enum values. |
enum_unmarshal |
false | Generate UnmarshalText for enum values. |
gen_setter |
false | Generate Set* methods for struct fields. |
gen_db_tag |
false | Generate db:"<fieldname>" struct tags. |
omitempty_for_optional |
true | Generate omitempty JSON tags for optional fields. |
use_type_alias |
true | Generate type aliases for typedef instead of type definitions. |
validate_set |
true | Generate code to validate uniqueness of set elements. |
value_type_in_container |
false | Use value types (not pointers) for struct-like types in containers. |
scan_value_for_enum |
true | Generate Scan and Value methods for enums.Implements database/sql interfaces. |
reorder_fields |
false | Reorder struct fields to improve memory layout. |
typed_enum_string |
false | Prefix the type name to enum string representations. |
keep_unknown_fields |
false | Generate code to store unrecognized fields in structs. |
gen_deep_equal |
false | Generate DeepEqual for structs, unions, and exceptions.Silently disabled when template=slim. |
compatible_names |
false | Append _ to names with a New prefix or Args/Result suffix. |
reserve_comments |
false | Preserve comments from the Thrift IDL in generated code. |
nil_safe |
false | Generate nil-safe getter methods. |
frugal_tag |
false | Generate frugal struct tags. |
unescape_double_quote |
true | Unescape double quotes in tag literals. |
gen_type_meta |
false | Generate and register type metadata for structs. |
gen_json_tag |
true | Generate json struct tags. |
always_gen_json_tag |
false | Generate json tags even when a go.tag annotation is present. |
snake_style_json_tag |
false | Use snake_case style for JSON tags. |
lower_camel_style_json_tag |
false | Use lowerCamelCase style for JSON tags. |
with_reflection |
false | Generate *-reflection.go files with runtime type metadata for structs.Required by with_field_mask. |
enum_as_int_32 |
false | Generate enum types as int32. |
trim_idl |
false | Remove unused definitions from the IDL before generating code. |
json_stringer |
false | Use JSON marshaling in the String() method. |
with_field_mask |
false | Generate field-mask support for structs. Also requires with_reflection. |
field_mask_halfway |
false | Support setting field-mask on non-root structs. |
field_mask_zero_required |
false | Write zero value for required fields filtered by field-mask. Default: write current value. |
thrift_streaming |
false | Recognize streaming annotations and generate streaming service methods. |
no_default_serdes |
false | Skip generating default Thrift serialization/deserialization code. |
no_alias_type_reflection_method |
false | Skip type reflection methods in *-reflection.go for types annotated withthrift.is_alias="true". |
enable_ref_interface |
false | Generate interface fields without pointer types for types annotated withthrift.is_interface="true" in referenced Thrift files. |
use_option |
false | Parse Thrift annotations into struct-style option fields. Unrecognized keys are silently ignored. |
streamx |
false | Generate streaming interfaces using streamx mode. Requires thrift_streaming. |
no_fmt |
false | Skip formatting of generated Go code. |
skip_empty |
false | Skip generating files that have no content. |
no_processor |
false | Skip generating the default Thrift processor and client. |
get_enum_annotation |
false | Generate GetAnnotation methods for enum types. |
apache_warning |
false | Call a runtime warning function in Read/Write methods when Apache codec is used. |
apache_adaptor |
false | Replace Read/Write bodies with delegate calls to the Kitex fast codec adaptor.Uses gopkg/protocol/thrift/apache/adaptor. |
skip_go_gen |
false | Skip Go code generation; only parse the IDL and execute plugins. |
code_ref |
false | Instead of regenerating types, import them from the package path specified in idl-ref.yaml. |
code_ref_slim |
false | Like code_ref but generates fewer local aliases to reduce import conflicts. |
exp_code_ref |
false | Like code_ref_slim but keeps some structs as local definitions. (experimental) |
keep_code_ref_name |
false | When using code_ref, write the ref file with the same filenameinstead of appending -ref.go. |
enable_nested_struct |
false | Generate nested fields when thrift.nested="true" is set on a field.Requires slim or raw_struct template. |
Explanations for flags that require more context than the table provides.
Controls how IDL identifiers (struct names, field names, etc.) are converted to Go identifiers. All three styles split on _ and capitalize words, with common initialisms like url, id, http upgraded to uppercase (URL, ID, HTTP) by default.
| Style | Key differences |
|---|---|
thriftgo (default) |
Capitalizes words that start with a lowercase letter; already-uppercase words are left unchanged. Does not append _ to any names. |
golint |
Follows stricter golint-style rules. Preserves leading underscores (_name stays _Name) and underscores between digits (v1_2 → V1_2). |
apache |
Replicates the apache/thrift Go generator. Names ending in Args or Result get an extra _ appended (GetUserArgs → GetUserArgs_). Uppercase words following _ keep an underscore prefix in the output. |
ignore_initialisms disables the initialism correction (user_url → UserUrl instead of UserURL).
thriftgo generates <FuncName>Args and <FuncName>Result structs for every RPC method. If your IDL defines a user struct whose name ends in Args or Result, or starts with New, the names collide. compatible_names appends _ to the user-defined name to resolve this.
# IDL
struct GetUserArgs { 1: string id } # would collide with generated GetUser_argsWithout compatible_names: compile error due to duplicate name. With it: GetUserArgs_ is generated instead.
By default, struct-like types inside list, set, or map are generated as pointer types:
// default
type MyStruct struct { Items []*Inner }With value_type_in_container:
// with value_type_in_container
type MyStruct struct { Items []Inner }Use this to avoid heap allocations when container elements are small and frequently iterated.
Generates an init() block in each file that registers every struct into a global metadata registry:
func init() {
meta.RegisterStruct(NewMyStruct, <serialized-IDL-bytes>)
}This enables runtime reflection-based construction of structs by name. Used by frameworks that need to instantiate types dynamically without knowing them at compile time.
Changes the generated String() method on structs to return a JSON representation instead of Go's default fmt.Sprintf("%+v", p)-style output. Useful when struct values are logged or printed and a JSON format is preferred.
These four flags work together to enable field-mask support — a mechanism for selectively serializing/deserializing only a subset of struct fields (similar to Protobuf FieldMask).
with_reflection: generates*-reflection.gofiles containing type descriptors (field names, IDs, types). Required by field-mask for path validation.with_field_mask: adds a_fieldmask *fieldmask.FieldMaskfield andSet_FieldMask()method to each struct.Read/Writethen consult the mask and skip excluded fields.field_mask_halfway: by default a field-mask may only be set on the root (top-level) struct. This option allows setting it on any nested struct. Note: if multiple parent objects share the same child, only one parent's mask will take effect.field_mask_zero_required: required fields that are excluded by a mask are normally still written with their current value. With this option they are written as zero values instead.
Minimal usage:
thriftgo -g go:with_field_mask,with_reflection service.thriftTwo flags, two levels of streaming support:
thrift_streaming: without this, any service method with a streaming annotation is silently dropped from the generated output. Enable it to retain and generate streaming methods.streamx: changes the generated streaming interface types to usegithub.com/cloudwego/kitex/pkg/streaming(the streamx API). Requiresthrift_streaming.
Use thrift_streaming alone when targeting the default Kitex streaming API. Add streamx when targeting the newer streamx API.
By default every struct gets Read(iprot thrift.TProtocol) and Write(oprot thrift.TProtocol) methods containing the full field-by-field serialization logic. With no_default_serdes, those method bodies are replaced with stub insertion points (ExtraFieldMap, ExtraStruct), allowing a plugin or external code to supply alternative serialization (e.g. Frugal, fast codec).
Two options for managing the coexistence of Apache Thrift codec and Kitex fast codec:
apache_warning: keeps the standard generatedRead/Writelogic but prepends a call toapache_warning.WarningApache(typeName)in each method. This emits a runtime log warning whenever the Apache codec path is taken, helping identify hot paths that should be migrated.apache_adaptor: replaces the entireRead/Writebody withapache_adaptor.AdaptRead(p, iprot)/apache_adaptor.AdaptWrite(p, oprot)fromgithub.com/cloudwego/gopkg. The adaptor transparently routes calls to Kitex fast codec. Use this when migrating existing Apache-codec-dependent code without changing call sites.
These are mutually exclusive: when apache_adaptor is set, the full Read/Write body (including any apache_warning call) is not generated.
When multiple services share types from a common IDL, regenerating that IDL for each service produces duplicate definitions. The code_ref family solves this by importing types from an already-generated package instead of regenerating them.
Requires an idl-ref.yaml (or idl-ref.yml) in the working directory that maps IDL paths to existing Go package paths:
ref:
path/to/shared.thrift: github.com/myorg/shared/gencode_ref: for each IDL with a ref entry, replaces local type generation with imports from the specified path. Generates a<name>-ref.gofile containing type aliases.code_ref_slim: generates fewer aliases thancode_ref, reducing the chance of import conflicts.exp_code_ref: likecode_ref_slimbut keeps some structs as local definitions rather than aliases (experimental).keep_code_ref_name: writes the ref file using the same filename as the normal output file instead of appending-ref.go.
Before generating, walks the IDL and removes all definitions (structs, enums, typedefs, etc.) that are not reachable from service definitions. Useful when a large shared IDL contains many types but only a small subset are used by a specific service.
A warning is printed showing how many definitions were trimmed:
[WARN] removed 42 unused structures with 187 fields
Thrift IDL allows arbitrary string annotations on fields and types. With use_option, annotations whose keys match known option definitions from the thrift_option extension are parsed into typed struct-style option fields in the generated code. Keys that do not match any known option are silently ignored.
By default every IDL field becomes a named, typed Go field. A field annotated with thrift.nested="true" is instead embedded anonymously (Go struct embedding), so its sub-fields are promoted to the parent struct. Only valid with the slim or raw_struct template; thriftgo automatically switches to slim if this option is set and no template is specified.
- Input: A single
.thriftIDL file as a positional argument. Additional include search paths via-i. - Stdin: Not used by the main tool. Plugins receive a serialized
Requeston stdin. - Stdout: Plugins write their serialized
Responseto stdout. - Stderr: Warnings and info logs (controlled by
-v/-q). - Output files: Written to
./gen-<lang>/<namespace>/by default. Override with-o.
Output is not written to stdout and cannot be piped directly.
No config file. All configuration is via flags and environment variables.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
THRIFTGO_DEBUG |
string | No | "" |
Set to 1 to enable CPU and heap profiling (writes thriftgo-cpu.pprof and thriftgo-heap.pprof). |
Precedence: flags > environment variables > defaults.
The code_ref, code_ref_slim, and exp_code_ref flags read an idl-ref.yaml (or idl-ref.yml) file from the working directory. It maps IDL file paths to an existing Go package path, so thriftgo imports types from that package instead of regenerating them.
ref:
path/to/shared.thrift: github.com/myorg/shared/genGenerate Go code with golint naming and setter methods:
thriftgo -g go:naming_style=golint,gen_setter example.thriftRecursively generate code for an IDL and all its includes:
thriftgo -r -g go service.thriftGenerate to a custom output directory with a package prefix:
thriftgo -o ./generated -g go:package_prefix=github.com/myorg/myproject service.thriftUse the slim template and skip formatting:
thriftgo -g go:template=slim,no_fmt service.thriftGenerate with field-mask and reflection support:
thriftgo -g go:with_field_mask,with_reflection service.thriftInvoke an external plugin alongside the Go generator:
thriftgo -g go -p my-plugin:option1=val1 service.thrift| Code | Meaning |
|---|---|
0 |
Success. |
2 |
Error: invalid arguments, IDL parse failure, semantic error, generation failure, or no output language specified. |
| Problem | Cause | Fix |
|---|---|---|
require exactly 1 argument for the IDL parameter |
No .thrift file given, or multiple positional arguments provided. |
Pass exactly one IDL file as the last argument. |
No output language(s) specified |
-g flag is missing. |
Add -g go (or another backend) to the command. |
found include circle |
Circular include chain in the IDL files. |
Break the circular dependency in the .thrift files. |
unsupported naming style |
Invalid value passed to naming_style=. |
Use one of: golint, apache, thriftgo. |
invalid argument for use_package |
use_package value is not in path=replacement form. |
Use the form use_package=some/pkg=replacement/pkg. |
| Plugin times out | Plugin takes longer than --plugin-time-limit. |
Increase the limit: --plugin-time-limit=5m, or set 0 for no limit. |
| Field-mask has no effect | with_field_mask used without with_reflection. |
Add with_reflection to the same -g options list. |
| Streaming functions missing from output | streamx used without thrift_streaming. |
Add thrift_streaming to the same -g options list. |
enable_nested_struct has no effect |
Not using the slim or raw_struct template. |
Add template=slim to the options list. |