📖 2 min read (~ 500 words).

Auto-configure

Normally you edit configure_*.go by hand to attach each handler. The auto-configure example takes a different route: generate with --implementation-package, point it at a package you write, and the generator emits the wiring for you. Every operation is routed to a method on your implementation — no hand-editing of a configure file.

Tip

Source: auto-configure/. Generated with swagger generate server --name AToDoListApplication --spec ./swagger.yml --implementation-package github.com/go-swagger/examples/auto-configure/implementation --principal any.

The generated contract

Instead of a configure_*.go, the generator produces auto_configure_*.go. It declares the Handler interface your package must satisfy, and binds a package-level Impl to your constructor via implementation.New():

var Impl Handler = implementation.New()

// Handler handles all api server backend configurations and requests
type Handler interface {
	Authable
	Configurable
	TodosHandler
}

// Configurable handles all server configurations
type Configurable interface {
	ConfigureFlags(api *operations.AToDoListApplicationAPI)
	ConfigureTLS(tlsConfig *tls.Config)
	ConfigureServer(s *http.Server, scheme, addr string)
	CustomConfigure(api *operations.AToDoListApplicationAPI)
	SetupMiddlewares(handler http.Handler) http.Handler
	SetupGlobalMiddleware(handler http.Handler) http.Handler
}

// Authable handles server authentication
type Authable interface {
	// Applies when the "x-todolist-token" header is set
	KeyAuth(token string) (any, error)
}

// TodosHandler
type TodosHandler interface {
	AddOne(params todos.AddOneParams, principal any) middleware.Responder
	DestroyOne(params todos.DestroyOneParams, principal any) middleware.Responder
	FindTodos(params todos.FindTodosParams, principal any) middleware.Responder
	UpdateOne(params todos.UpdateOneParams, principal any) middleware.Responder
}

Full source: auto-configure/restapi/auto_configure_a_to_do_list_application.go

Each generated handler then simply delegates to that Impl:

	api.TodosAddOneHandler = todos.AddOneHandlerFunc(func(params todos.AddOneParams, principal any) middleware.Responder {

		return Impl.AddOne(params, principal)
	})

Full source: auto-configure/restapi/auto_configure_a_to_do_list_application.go

Your implementation package

You write a package that implements Handler. This is ordinary hand-written code — nothing generated — so it’s the natural home for your business logic. Here’s the AddOne method backing the in-memory store:

func (i *TodosHandlerImpl) AddOne(params todos.AddOneParams, principal any) middleware.Responder {
	_ = principal

	i.lock.Lock()
	defer i.lock.Unlock()
	newItem := params.Body
	if newItem == nil {
		return todos.NewAddOneDefault(http.StatusBadRequest).
			WithPayload(&models.Error{
				Code:    http.StatusBadRequest,
				Message: &[]string{"Item Body is nil"}[0],
			})
	}
	// assign new id
	newItem.ID = i.idx
	i.idx++

	i.items[newItem.ID] = newItem
	return todos.NewAddOneCreated().WithPayload(newItem)
}

Full source: auto-configure/implementation/todos_impl.go

The example splits the interface across small types — TodosHandlerImpl, ConfigureImpl, AuthImpl — composed by a single HandlerImpl that New() returns. That keeps handlers, server configuration, and authentication in separate files while still satisfying the one generated Handler interface.

When to use it

Auto-configure shines when you regenerate often and don’t want a hand-edited configure_*.go in the loop: your implementation lives entirely in a package you own, and regeneration only ever touches the generated wiring. It’s also a clean way to keep the transport-facing glue separate from your domain code.