interfacify

command module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2026 License: MIT Imports: 6 Imported by: 0

README

interfacify logo

interfacify

Test Go Report Card Go Reference Release Dependencies

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 ./...

Documentation

Overview

interfacify

Turn a structs into interfaces. When a struct embeds a struct or interface that exports methods these methods are added to the interface this behaviour is controlled via -deep=true (default).

Assuming the following structs:

package examples

// A handles A and C flags lookup
type A struct{ *C }

// HasA true if A is true
func (*A) HasA() bool { return true }

type iC interface{ HasC() bool }

// B handles B and C flags lookup
type B struct{ iC }

// HasB true if B is true
func (*B) HasB() bool { return true }

type C struct{}

// HasC true if C is true
func (*C) HasC() bool { return true }

Running the following command:

interfacify -structs git.host/examples.A,git.host/examples.B -ofile generated.go -deep -pkg examples -suffix Interface

Results in

package examples

// AInterface is an interface matching git.host/examples.A
//
// A handles A and C flags lookup
type AInterface interface {
    // HasA true if A is true
    HasA() bool
    // HasC true if C is true
    HasC() bool
}

// BInterface is an interface matching git.host/examples.B
//
// B handles B and C flags lookup
type BInterface interface {
    // HasB true if B is true
    HasB() bool
    // HasC true if C is true
    HasC() bool
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL