go-method-gen
is a development utility that generates Equal
, Diff
, and Merge
functions for Go structs using reflection. It is designed to reduce boilerplate and promote consistent comparison and merging behavior across complex structures.
This tool is useful for applications involving configuration merging, object synchronization, and state comparison.
- Generate equality functions: Check deep equality between two struct instances.
- Generate diff functions: Return field-level differences between structs.
- Custom field overrides: Provide fine-grained diff/equality behavior via YAML override files.
- Header injection: Add license or documentation header to generated code.
- Module path replacement: Use local module paths for
eqdiff
or any dependency. - CLI compatible: Usable as a standalone binary or as a scriptable tool in CI/CD.
- Directory scanning: Automatically scan a directory for Go types with --scan.
The generated Equal
function checks for deep equality across fields:
func (rec StructA) Equal(obj StructA) bool {
return EqualMapStringString(rec.maps, obj.maps) &&
EqualMapIntPointerA(rec.mapA, obj.mapA)
}
The generated Diff
function returns a list of changed fields:
func (rec StructA) Diff(obj StructA) map[string][]interface{} {
diff := make(map[string][]interface{})
for diffKey, diffValue := range DiffMapStringString(rec.maps, obj.maps) {
diff["maps"+diffKey] = diffValue
}
for diffKey, diffValue := range DiffMapIntPointerA(rec.mapA, obj.mapA) {
diff["mapA"+diffKey] = diffValue
}
return diff
}
go install github.com/<TBD>/go-method-gen/cmd/go-method-gen/@latest
Or build from source:
git clone https://github.com/<TBD>/go-method-gen
cd go-method-gen
go build -o go-method-gen
go-method-gen [flags] importpath.TypeName [...]
You must provide fully-qualified type paths (importpath.TypeName), unless using --scan.
Alternatively, use the --scan flag to automatically discover all types in a directory:
go-method-gen --scan=./path/to/pkg [flags]
Options:
option | functionality |
---|---|
--output-dir=DIR | Path to write generated code (default: ./generated) |
--keep-temp | Keep temporary working files (.eqdiff-tmp) for inspection |
--debug | Enable verbose output (shows parsed args, generated code, etc.) |
--replace-gomethodgen=DIR | Use a local path for the go-method-gen module |
--replace=MOD:LOCALPATH | Add a replace directive in the generated go.mod (can be used multiple times) |
--overrides=FILE.yaml | YAML file to override diff/equal logic for specific fields |
--header-file=PATH | Optional Go file to prepend as header in generated output |
--scan=DIR | Scan a directory to extract all types (exclusive with type arguments) |
You must provide fully-qualified type paths (importpath.TypeName
) if not using scan option.
Each type must be specified using the following format:
importpath.TypeName
You may also include an optional version suffix using Go module semantics:
importpath.TypeName@version
Input | Description |
---|---|
github.com/example/project/config.StructConfig | Uses the current module version available in your environment |
github.com/example/project/[email protected] | Forces resolution of the module at v1.4.2 |
my/local/module/pkg.MyType | Local import path (must be resolvable via go get or replace) |
my/local/module/pkg.MyType@latest | Gets the latest version from the module proxy |
💡 Note: The version suffix applies only to the module part of the import path. The tool will extract the type name from the final segment after the last dot (.) and use Go reflection to generate equality, diff code.
go-method-gen --keep-temp --debug --replace-gomethodgen=/home/user/dev/go-method-gen github.com/example/project/config.StructConfig
This generates methods like Equal
, Diff
, and Merge
for StructConfig
, stores intermediate files, outputs debug logs, and uses a local path for the eqdiff
module.
You can override the default code generation for specific types by providing a YAML file via the --overrides=FILE.yaml option.
This is useful when:
-
You want to reuse hand-written comparison or diff logic,
-
The type is not safe or meaningful to reflect on (e.g. generics, external types),
-
You need optimized or domain-specific equality logic.
Each key in the YAML map must be a fully-qualified type path (importpath.TypeName), and must define either or both of:
equal: Custom equality function
diff: Custom diff function
Each function override must provide:
pkg: the import path of the package containing the function
name: the name of the function
github.com/myorg/myproject/pkg/structs.StructA:
equal:
pkg: "github.com/myorg/myproject/pkg/structs/funcs"
name: "EqualStructA"
diff:
pkg: "github.com/myorg/myproject/pkg/structs/funcs"
name: "DiffStructA"
github.com/myorg/data/v5/models.Acls:
equal:
pkg: "github.com/myorg/myproject/pkg/structs/funcs"
name: "EqualAcls"
diff:
pkg: "github.com/myorg/myproject/pkg/structs/funcs"
name: "DiffAcls"
This example tells go-method-gen to use the custom functions EqualStructA and DiffStructA for StructA, and EqualAcls and DiffAcls for models.Acls.
These functions must have the correct signature, typically:
func EqualStructA(a, b StructA) bool
func DiffStructA(a, b StructA) map[string][]interface{}
💡 The specified packages will automatically be imported in the generated file, and the functions will be used instead of auto-generated ones.