brandur.org

I’ve updated The Two-phase Data Load and Render Pattern in Go after Roman pointed out that if we swap the position of two generic parameters in Render, another generic parameter can be inferred, and every invocation gets considerably cleaner.

Previously, Render looked like this:

func Render[TLoadBundle any, TRenderable Renderable[TLoadBundle, TModel, TRenderable], TModel any](
    ctx context.Context, e db.Executor, baseParams *pbaseparam.BaseParams, model TModel,
) (TRenderable, error)

And was invoked like:

resource, err := apiresource.Render[*apiresourcekind.ProductLoadBundle, *apiresourcekind.Product](
  ctx, tx, svc.BaseParams, product
)

In the updated version, the positions of the first two generic parameters are swapped:

func Render[TRenderable Renderable[TLoadBundle, TModel, TRenderable], TLoadBundle any, TModel any](
    ctx context.Context, e db.Executor, baseParams *pbaseparam.BaseParams, model TModel,
) (TRenderable, error) {

And the function can now be invoked like this:

resource, err := apiresource.Render[*apiresourcekind.Product](
  ctx, tx, svc.BaseParams, product
)

Much cleaner. A caller no longer even needs to know that the load bundle exists. At work I applied the fix to our hundreds of lines of existing calls, and the difference in readability is night and day.