As a code-generator first application, we have the following structure:
cmd
- The home of the code generator application to be invoked withgo generate ...
pkg
- The layers of the application to parse an incoming file and validate to actual file generationexample
- The example with a couple of interfaces being middleware'd
Simply put, one can write a simple Foo
interface with a common
Middleware
function type as type Middleware func(Foo)Foo
//go:generate go run middleware-generator Service SvcMiddleware tracer
package pkg
type Service interface {
Foo(bar string) string
}
type SvcMiddleware func(Service) Service
What this will do is generate a new file alongside the target file
prepended with logger_
and implements the given Service
with a factory
method called NewService
. It's not necessary to call these types Service,
but the types themselves must exist.
An example service that gets generated:
// Code generated by "logger-middleware Service SvcMiddleware tracer"; DO NOT EDIT.
// Copyright (c) 2022 Merit International Inc. All Rights Reserved
package example
import (
"context"
domain "github.com/gabizou/middleware-generator/example/domain"
zipkingo "github.com/openzipkin/zipkin-go"
)
func NewServiceTracer(tracer zipkingo.Tracer) SvcMiddleware {
return func(s Service) Service {
return &tracerS{
s: s,
tr: tracer,
}
}
}
type tracerS struct {
tr zipkingo.Tracer
s Service
}
func (t *tracerS) Foo(ctx context.Context, bar string) domain.Merit {
span, ctx := t.tr.StartSpanFromContext(ctx, "Foo")
defer func() {
span.Finish()
}()
return t.s.Foo(ctx, bar)
}
golang.org/x/tools
: Standard library tools to parse and resolve types of the source filegolang.org/go/types
: Standard library code for representing and interpreting the AST in gogithub.com/dave/jennifer
: Code generation library to simplify actual AST -> source code