interfacify

interfacify generates Go interfaces from one or more concrete types.
It resolves packages from one or more Go module or workspace paths, collects exported methods for each requested type, preserves doc comments when it can resolve them from source, and writes formatted Go code to -ofile.
With -deep=true, exported methods promoted through embedded local structs or interfaces are included in the generated interface.
Install
Install the command directly:
go install github.com/thetechpanda/interfacify@latest
Or add it as a Go tool dependency in the module where you want to use it:
go get -tool github.com/thetechpanda/interfacify@latest
go tool interfacify -help
That pins the tool in your go.mod, so the project can run a consistent version with go tool interfacify.
This repository currently requires Go 1.26.1, so the go tool flow assumes your module is already using Go 1.26.1+ or can auto-switch toolchains.
Or build it from this repository:
go build -o interfacify .
To inspect the CLI without building a binary:
go run . -help
Usage
interfacify \
-paths . \
-structs example.com/project/examples.A,example.com/project/examples.B \
-ofile generated.go \
-pkg examples \
-suffix Interface \
-deep=true
The same invocation works through go tool once the tool is added to your module:
go tool interfacify \
-paths . \
-structs example.com/project/examples.A,example.com/project/examples.B \
-ofile generated.go \
-pkg examples \
-suffix Interface \
-deep=true
Flags
| Flag |
Default |
Description |
-paths |
. |
Comma-separated list of module or workspace paths to search. The first matching path wins for each import path. |
-structs |
"" |
Comma-separated list of fully-qualified type names to convert. |
-ofile |
generated.go |
Output file path for the generated Go source. |
-pkg |
output |
Package name to use in the generated file. |
-prefix |
"" |
Optional prefix for generated interface names. |
-suffix |
"" |
Optional suffix for generated interface names. |
-deep |
true |
Include exported methods promoted through embedded local structs or interfaces. |
When generating into the same package as the source types, use -prefix or -suffix to avoid redeclaring the original type names.
Examples
All examples below assume you are running from the repository root and use the fixture modules under pkg/test_data.
Basic embedded methods
Generate two interfaces from the _basic fixture, including exported methods promoted through embedding:
go run . \
-paths ./pkg/test_data/_basic \
-structs example.com/interfacify-basic/examples.A,example.com/interfacify-basic/examples.B \
-ofile ./tmp/basic_deep.go \
-pkg examples \
-prefix Prefix \
-suffix Suffix \
-deep=true
This matches pkg/test_data/_basic/expected_deep.golden.
Shallow generation
Generate only methods declared directly on A from the same fixture:
go run . \
-paths ./pkg/test_data/_basic \
-structs example.com/interfacify-basic/examples.A \
-ofile ./tmp/basic_shallow.go \
-pkg examples \
-prefix Prefix \
-suffix Suffix \
-deep=false
This matches pkg/test_data/_basic/expected_shallow.golden.
Package path vs module path
-structs must point at the package that owns the type, not just the module root. In _basic, A lives in the examples package:
go run . \
-paths ./pkg/test_data/_basic \
-structs example.com/interfacify-basic/examples.A \
-ofile ./tmp/basic_single.go \
-pkg main
That generates:
package main
// A is an interface matching example.com/interfacify-basic/examples.A
type A interface {
HasA() bool
HasC() bool
}
Imported types in method signatures
Generate an interface from the _imports fixture and keep the output in the source package:
go run . \
-paths ./pkg/test_data/_imports \
-structs example.com/interfacify-imports/service.Runner \
-ofile ./tmp/imports.go \
-pkg service \
-prefix Prefix \
-suffix Suffix
This matches pkg/test_data/_imports/expected.golden.
Generate into a different package
If a method signature only uses imported types, you can emit the interface into another package:
go run . \
-paths ./pkg/test_data/_different_pkg \
-structs example.com/interfacify-differentpkg/service.Runner \
-ofile ./tmp/different_pkg.go \
-pkg generated \
-prefix Prefix \
-suffix Suffix
This matches pkg/test_data/_different_pkg/expected.golden.
Nested embedded methods
Generate an interface from the _nested fixture to include methods promoted through multiple embedded layers:
go run . \
-paths ./pkg/test_data/_nested \
-structs example.com/interfacify-nested/nested.Top \
-ofile ./tmp/nested.go \
-pkg nested \
-prefix Prefix \
-suffix Suffix
This matches pkg/test_data/_nested/expected.golden.
Multifile package
Generate an interface from a package spread across multiple files:
go run . \
-paths ./pkg/test_data/_multifile \
-structs example.com/interfacify-multifile/service.Worker \
-ofile ./tmp/multifile.go \
-pkg service \
-prefix Prefix \
-suffix Suffix
This matches pkg/test_data/_multifile/expected.golden.
Generic interface and struct
Generate interfaces from the _generics fixture. The generated interfaces preserve source type parameters:
go run . \
-paths ./pkg/test_data/_generics \
-structs example.com/interfacify-generics/service.Reader,example.com/interfacify-generics/service.Loader \
-ofile ./tmp/generics.go \
-pkg service \
-prefix Prefix \
-suffix Suffix
This matches pkg/test_data/_generics/expected.golden.
Multiple type parameters
Generate interfaces from the _generics_multi fixture to preserve multiple type parameters and promoted methods from an embedded generic interface:
go run . \
-paths ./pkg/test_data/_generics_multi \
-structs example.com/interfacify-generics-multi/service.Pair,example.com/interfacify-generics-multi/service.Entry \
-ofile ./tmp/generics_multi.go \
-pkg service \
-prefix Prefix \
-suffix Suffix
This matches pkg/test_data/_generics_multi/expected.golden.
Multiple lookup paths
Search more than one local module path. The first path that can resolve the import path wins:
go run . \
-paths ./pkg/test_data/_imports,./pkg/test_data/_basic \
-structs example.com/interfacify-basic/examples.A \
-ofile ./tmp/multi_paths.go \
-pkg examples \
-prefix Prefix \
-suffix Suffix \
-deep=false
Even though _imports is listed first, the generator falls through to _basic because that is the first path containing example.com/interfacify-basic/examples.
Constraints
- Use
-paths to tell the generator which local modules or workspaces it may search. The default is the current directory.
-structs entries must be fully-qualified import paths followed by the type name.
- If a method signature refers to local package types, the generated file must stay in the same package as the source.
- Embedded method promotion only follows local embedded structs and interfaces.
Tests
go test ./...