CLI tool
hexdigest/gowrap avatar
hexdigest/gowrap

GoWrap: generated decorators for Go interfaces

GoWrap is a command line tool for generating decorators for Go interfaces

1,339 stars95 forksGoMIT

At a glance

What is it?
GoWrap generates Go interface decorators from local or hosted templates, adding metrics, logging, fallbacks, timeouts, retries, and other cross-cutting behavior. It suits Go projects that want generated wrapper code, but reviewers must account for template inputs and regeneration dependencies.
Who is it for?
GoWrap is appropriate for Go maintainers that want repeatable, template-based interface wrappers and can manage generated files. It is a poor fit for projects that require handwritten control flow without generated dependencies.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 51 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

GoWrap targets repetitive interface behavior

GoWrap solves a narrow code-generation problem: adding behavior around methods declared by a Go interface without editing each call site that consumes the interface. It is aimed at Go developers working with abstractions such as `io.Reader`, application connectors, RPC clients, storage interfaces, and other components that can be passed around as interface values.

The practical cases include Prometheus metrics, structured logging, retry loops, fallback implementations, method timeouts, request validation, and connection selection. The same underlying shape applies across these cases. The source interface identifies the required methods, a template defines the wrapper behavior, and generated code supplies a concrete implementation that delegates to another value. This is useful when changing a service interface should not require tracing every consumer that may need logging, limits, or resilience behavior.

The generated decorator becomes a source artifact that participates in normal Go builds. GoWrap does not promise runtime interception of arbitrary method calls. It generates a type from a selected interface and template, so the application must use that generated implementation at its composition point. That distinction matters: GoWrap reduces repeated wrapper code, but it does not make existing implementations acquire decorator behavior automatically.

From interface selection to emitted Go wrapper

The repository is organized around command handling, loading, generation, printing, and templates. At the top level, command-related Go files sit beside directories such as `cmd/`, `generator/`, `loader/`, `printer/`, and `templates/`. Based on that layout, the visible flow begins with CLI arguments, identifies an interface through its Go package, resolves a template, loads interface information, and prints the resulting Go source.

Template resolution has a deliberate precedence rule. The `-t` value is first treated as a local file name. If no matching local file exists, GoWrap looks for that name in its repository template collection. The documentation also states that a template can be an HTTPS URL. This allows the same command shape to select project-owned template code or a template hosted by the project.

Templates determine the generated method bodies and configuration surface. For example, the `prometheus` template instruments interface methods, while `fallback` runs multiple implementations and returns the first non-error result. Other built-in choices include `retry`, `timeout`, `logrus`, `caching`, `ratelimit`, and `syncpool`. GoWrap also supports template parameters through repeated `-v` arguments. A parameter with an equals sign supplies a key and value, such as `DecoratorName=MyDecorator`; an argument without an equals sign is treated as a boolean.

By default, output includes a `//go:generate` instruction. This makes the generation command part of the source file rather than leaving the provenance only in developer notes. The trade-off appears when a remote template URL is used: regeneration then requires network access.

Installing GoWrap and generating a first wrapper

The current `go.mod` declares Go 1.24.0 and the `go1.24.2` toolchain, so the installed Go toolchain must be able to satisfy that module requirement. The README's direct CLI installation command installs the latest published version of the command package.

bash
go install github.com/hexdigest/gowrap/cmd/gowrap@latest

After installation, Go places the command in the Go binary directory when `GOBIN` is set, or in the user binary directory when it is not. The README does not document the resulting path. The command must therefore be available through the shell's `PATH`.

For a first generation, select the source interface with `-p` and `-i`, choose a template with `-t`, and name the output with `-o`. This example generates a Prometheus-instrumented wrapper for `io.Reader`.

bash
gowrap gen -p io -i Reader -t prometheus -o reader_with_metrics.go

The expected result is a new `reader_with_metrics.go` file containing a generated implementation of the `io.Reader` interface. The output may also contain a `//go:generate` instruction because that is the default. Review the generated imports, constructor shape, delegation path, and metric definitions before incorporating it. A later interface change can then trigger regeneration through GoWrap's generated instruction, provided the source package and template remain available.

Hosted templates and regeneration constraints

GoWrap's template system is its main extension point. Local files have priority, repository templates are the fallback, and HTTPS URLs can reference hosted templates. This makes it possible to keep organization-specific behavior in a source-controlled file while retaining the same generator interface.

A local template is the more predictable choice for reproducible builds because regeneration does not depend on retrieving an HTTPS resource. The README specifically warns that generated instructions containing a remote template URL require an internet connection. It also advises copying templates when offline regeneration is required, although the truncated README does not show the complete command for doing that.

Template names are simple, but behavior is not interchangeable. Selecting `timeout` affects methods that accept a context, as stated in the template description. Selecting `validate` checks arguments that expose a `func Validate() error` method. Selecting `circuitbreaker` changes execution after a configured number of consecutive errors and resumes after a delay. Selecting `robinpool` selects among implementations with round-robin behavior, while `syncpool` uses `sync.Pool`.

That variety introduces a review boundary. The interface and output path alone do not tell a maintainer what runtime policy the generated code will apply. Generated files must be reviewed as code, especially when a template pulls in logging, metrics, tracing, cache, or RPC validation libraries. The repository layout separates hosted templates from tests under `templates_tests/`, but the README does not describe every template parameter or its defaults.

Fallback, pooling, and timeout templates carry policy

GoWrap is more than a logging wrapper, which makes its template choice a design decision. The `fallback` template concurrently runs several interface implementations when an earlier attempt has not returned within a specified period, then returns the first non-error result. This approach can mask differences between implementations and changes failure timing, so the generated code needs review against the service contract.

The `ratelimit` template applies both requests-per-second and concurrent-call limits. The `retry` template adds retries, while `circuitbreaker` stops method execution after a specified run of consecutive errors. These policies belong outside core business logic when code generation makes them repeatable, but they still require operational configuration. The README lists the policies without publishing a complete parameter reference for each one.

The `prometheus` template instruments interface methods. The `logrus`, `opencensus`, `opentelemetry`, `opentracing`, and `elastic apm` templates add their respective telemetry styles. Those choices affect dependencies and generated imports even when application logic remains unchanged. The `caching` template uses the `go-cache` library for in-memory caching. The documentation does not describe cache invalidation, serialization behavior, or concurrency guarantees, so those points cannot be inferred from the template summary.

This is where GoWrap differs from writing one handcrafted wrapper. A handwritten wrapper gives direct control over every branch and dependency, but it must be maintained as the interface evolves. GoWrap centralizes method shape in a template and emits ordinary Go source. It reduces duplication, while moving review toward template selection and generated-code inspection.

Go 1.24 requirements, maintenance, and license

The repository's `go.mod` requires Go 1.24.0 and specifies the `go1.24.2` toolchain. This requirement affects developers who run GoWrap directly and may also affect generated output if templates import packages tied to the application's supported Go version. Upgrade planning should account for the toolchain version declared by this module, not merely the `v1.4.3` release tag.

The repository is not archived. Its last push was on 2026-09-02, and recent releases include `v1.4.3` on 2025-08-21, `v1.4.2` on 2025-02-13, and `v1.4.1` on 2024-12-11. The README does not promise release frequency or a compatibility policy for every hosted template.

Generation also creates an ongoing maintenance choice. Applications should keep generated files synchronized with interface changes, review template updates, and avoid silently accepting unrelated changes after running `go generate./...`. Remote template URLs add a network dependency and make the generation source less local than a checked-in template.

GoWrap is distributed under the MIT license. That permits use, modification, distribution, and sublicensing subject to the license text and notice conditions. This is a license summary rather than legal advice. Organizations should retain the project's `LICENSE` file and review their own distribution policy for generated code and third-party template dependencies.

Editorial conclusion

GoWrap is appropriate for Go maintainers that want repeatable, template-based interface wrappers and can manage generated files. It is a poor fit for projects that require handwritten control flow without generated dependencies. Check the selected template's imports and behavior, inspect the first generated implementation, and confirm that regeneration is reproducible before adoption.

Frequently asked questions

How do I install GoWrap?

The README gives `go install github.com/hexdigest/gowrap/cmd/gowrap@latest` for CLI installation. The repository's `go.mod` declares Go 1.24.0 and toolchain `go1.24.2`.

Which GoWrap template should I use for Prometheus metrics?

Use the `prometheus` template, which instruments the source interface with Prometheus metrics. The README's example passes it through `-t prometheus`.

Can GoWrap regenerate a decorator after an interface changes?

By default, GoWrap adds a `//go:generate` instruction, so the README says `go generate ./...` can regenerate decorators. Remote templates require internet access unless the template is copied locally.

Official sources

  1. hexdigest/gowrap on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/hexdigest-gowrap.svg)](https://hysenlabs.com/projects/hexdigest-gowrap)

Was this useful?