# wrapgen **Repository Path**: mirrors_kevinconway/wrapgen ## Basic Information - **Project Name**: wrapgen - **Description**: Interface wrapper generator for Go - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-08-09 - **Last Updated**: 2026-03-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # wrapgen - A code generator for Go interfaces # No Longer Maintained I recommend using as an alternative. As of 2024-06-21, [GoWrap](https://github.com/hexdigest/gowrap) is a maintained project that solves the exact same problem as this project and has been updated to support generics. This tool should still work for Go code that does *not* use generics. I do not plan to update the tool for generics or any other type system additions in the future. ## Old Documentation This project can inject the details of any Go interface into a custom template. The goal is to enable teams who either make frequent use of interface wrappers to layer on behavior, such as using a decorator pattern, or teams who often need to generate standard implementations of some interfaces, such as those generating stubs for a test. This project is heavily inspired by which contains a tool called `mockgen` that can generate an advanced mock implementation of any Go interface. ## Usage ### Quick Example ```bash go install github.com/kevinconway/wrapgen/v2 go install golang.org/x/tools/cmd/goimports ${GOPATH}/bin/wrapgen \ --source=io \ --interface=Reader \ --interface=Writer \ --package=wrappers \ --template="https://raw.githubusercontent.com/kevinconway/wrapgen/master/templates/logtime.txt" \ | ${GOPATH}/bin/goimports ``` The output will look like: ```golang package wrappers // Code generated by wrapgen DO NOT EDIT import ( "io" "log" "time" ) type WrapsReader struct { wrapped io.Reader } func (w *WrapsReader) Read(p []byte) (int, error) { start := time.Now() defer func() { log.Println("Read latency:", time.Now().Since(start)) }() var n, err = w.wrapped.Read(p) return n, err } type WrapsWriter struct { wrapped io.Writer } func (w *WrapsWriter) Write(p []byte) (int, error) { start := time.Now() defer func() { log.Println("Write latency:", time.Now().Since(start)) }() var n, err = w.wrapped.Write(p) return n, err } ``` All output is written to `stdout` and `stderr` by default. An optional destination file may be provided as an alternative to `stdout`. Template paths may either be URLs or file system paths. It is highly suggested to use `goimports` or another formatter as a post-processor. ### Overrider Example ```bash ${GOPATH}/bin/wrapgen \ --source=io \ --interface=Reader \ --interface=Writer \ --package=wrappers \ --template="https://raw.githubusercontent.com/kevinconway/wrapgen/master/templates/overrider.txt" \ | ${GOPATH}/bin/goimports ``` The output will look like: ```golang package wrappers // Code generated by wrapgen DO NOT EDIT import ( srcPkgAlias "io" ) type ( ReadFunc func(p []byte) (int, error) ) type TestReader struct { Reader srcPkgAlias.Reader ReadFunc ReadFunc } func (t *TestReader) Read(p []byte) (int, error) { if t.ReadFunc != nil { return t.ReadFunc(p) } return t.Reader.Read(p) } var _ srcPkgAlias.Reader = (*TestReader)(nil) type ( WriteFunc func(p []byte) (int, error) ) type TestWriter struct { Writer srcPkgAlias.Writer WriteFunc WriteFunc } func (t *TestWriter) Write(p []byte) (int, error) { if t.WriteFunc != nil { return t.WriteFunc(p) } return t.Writer.Write(p) } var _ srcPkgAlias.Writer = (*TestWriter)(nil) ``` ### CLI Options ```bash wrapgen --help Usage of wrapgen: --destination string Filename for the rendered template. Defaults to STDOUT. (default "-") --interface strings The name of the interface to render. --leftdelim string Left-hand side delimiter for the template. (default "#!") --package string The package name that the resulting file will be in. Defaults to the source package. --rightdelim string Right-hand side delimiter for the template. (default "!#") --source string The import path of the package to render. --template string The template to render. --timeout duration Maximum runtime allowed for rendering. (default 1m0s) ``` Any number of interfaces may be given by providing more `--interface` flags. ### Writing Templates The `templates/basic.txt` template from this project is the best way to get started writing your own. It demonstrates the how to manage import statements, iterate over the collected interfaces, and already covers the complexity of rendering method arguments and outputs correctly. Whether using `template/basics.txt` as a starter or generating a new template from scratch, the template content must be valid `text/template` markup. By default, the character sets `#!` and `!#` are used as the left and right delimiters, respectively. Those characters are the default because they rarely, if ever, conflict with common character sets in Go code. You can adjust these with CLI flags. The root context injected into the template is `Package` from the following: ```golang // Package is a container for all exported interfaces of a Go package. type Package struct { Name string Source *Import Interfaces []*Interface Imports []*Import // ImportsWithSource will contain Source if the destination package is set and // Source is not included in Imports. ImportsWithSource []*Import } // Import is a package name and path that is imported by another package. type Import struct { Package string Path string } // Interface is an exported interface defined in a package. type Interface struct { SrcType Type Name string Methods []*Method } // Method is a named function attached to an interface. type Method struct { Name string In []*Parameter Out []*Parameter } // Parameter is a named parameter used by a Method. type Parameter struct { Name string Type Type } // Type is a Go type definition that can be rendered into a valid // Go code snippet. type Type interface { String() string } ``` Those are the structures available within any template. Each `Type` is specialized and will render correctly when calling `String()`. For example, a `Parameter` with `Type` of read-only channel of integers will render as `<-chan int` when calling `String()` on the type. The `templates/basic.txt` template contains examples of inspecting the type string in order to support variadics. This practice can be extended to, for example, determine if the first parameter is a context and optionall fetch a value from it. ## License This project is available under the Apache2.0 license. See the `LICENSE` file in this repository for the complete license text.