Build1 distinct publisher3 min readUpdated
Five Go generators write DI containers, mappers and fixtures as plain committed code. The cost is a generation step; the payoff is wiring the compiler and debugger can see.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A set of five Go code generators called kanna has been published on dev.to with an argument attached: the constructor wiring, type conversion and test-fixture code that most Go projects hand to a reflection-based library should instead be generated as plain Go and committed to the repository [0][1][2][3]. The trade is stated plainly by the author, who accepts a generation step and a generated file in every diff in exchange for wiring you can read in code review, see in git diff, and step through in a debugger, rather than behaviour hidden inside a library at runtime [2][14].
The set covers dependency injection, struct mapping, test fixtures, ORM row scanning and i18n, installs as independent go tools so a project can adopt just one, and emits plain Go with no runtime reflection [4][6][7]. There is no registration step; the input is the struct declarations and struct tags already in the codebase [5]. kanna-di treats any package-level function whose first return value is a named type, a pointer to one, or an interface as a provider, with a trailing error permitted, and finds them by scanning the packages it is pointed at [8]. A container is a struct whose fields carry a di tag [9]. Running go generate writes di_gen.go beside the source, holding a constructor that calls the providers in dependency order [10]. If anything in the chain returns an error, the generated constructor returns and propagates one [11]. Where several providers match a field, the generator refuses to choose and reports the field position with the candidate list [12]. A //kanna:container comment sets the constructor name, the return type, and whether a MustNew variant is emitted [13].
kanna-fixture writes one constructor per struct in the target package with every field pre-filled, so a test names only the values it cares about through setter functions [15][19]. Field names drive inference, so Email gets gofakeit.Email() and Name gets gofakeit.Name(), and a tag such as fake:"{number:18,65}" overrides the guess [17]. Every exported struct is covered with nothing to opt into, which the author presents as the reason fixtures do not fall behind the model [18]. Types beyond gofakeit, such as uuid.UUID, are handled, and the generator says so when the destination module does not yet require the needed package [20].
The honest accounting is that failures do not all land at compile time. Ambiguous providers fail at generate time [12]; generated code that no longer type-checks against changed structs fails at build, which is the actual substance of the claim against reflection [1]; and fixtures keep one runtime caveat, since generation is deterministic but the values are not, so a test needing the same data twice must call gofakeit.Seed [21].
Two caveats about the material itself. Only kanna-di and kanna-fixture are shown with generated output; mapping, ORM and i18n are named but not demonstrated [2]. And the write-up inventories the set twice, once as DI, mapping, fixtures and ORM, once with i18n added, which is a small sign of how settled the boundaries are [4][c4b][3].
Worth watching: whether the DO NOT EDIT files stay current under review pressure in a repository that is not the author's [22], and whether refusing to pick between candidate providers reads as safety or as friction once a container carries a few dozen fields [12].
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
Your structs are the source of truth: the input for all the generators is the struct declarations and struct tags you already have, and nothing gets registered anywhere.
When several providers match, kanna-di does not pick one silently: it emits an error with the field's position and the list of candidates.
The write-up was published on dev.to under the headline 'I built five code generators to delete Go boilerplate'.
The author states that writing Go means writing the same mechanical code repeatedly: constructor wiring, conversions between domain types and API types, test fixtures, row scanning, and message localization.
The author states there are plenty of libraries that erase this boilerplate with runtime reflection, but that this moves failure to runtime and hides the behavior inside the library.
The author's stated approach is to generate the code you were going to write anyway and commit it to the repository.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Detailed primary source, no corroboration
The write-up is unusually specific for a self-published tool post: exact install and invocation commands, the tag and comment syntax, and full generated files for three of the five generators, all of which a reader could reproduce. But it is a single source authored by the tool's creator, with no independent testing, no repository metrics, no second publisher, and an internal contradiction about the toolset's scope. That caps evidentiary strength at roughly a third of the scale.
Availability only, no usage signal
The material establishes that the tools exist and can be installed, and nothing more. There are no downloads, stars, contributors, dependent projects, production deployments, releases or third-party user reports in the supplied source, so an adoption score would be invented rather than measured.
Mildly overstated
The headline promises to 'delete Go boilerplate' across five generators, and the scope blurb asserts that nothing gets registered anywhere. The body substantiates three generators, never demonstrates ORM or i18n, disagrees with itself about i18n's inclusion, and the mapper section requires converters to be registered once. The mechanism-level claims that are shown look sober and are not inflated, so the gap is modest and positive rather than large.
Author is the tool's creator
The item is a first-person launch write-up by the person who built kanna, published on a developer platform where such posts serve project promotion and personal reach. Framing choices follow that incentive: a superlative headline, a scope list including undemonstrated components, and no comparison with incumbent Go generators or discussion of maintenance burden. Nothing suggests undisclosed commercial sponsorship, so this is ordinary self-promotion rather than concealed interest.
Moderate on description, low on performance
Confidence is high that the write-up says what the claims report and that the shown generated code is what the tools emit for the given examples, because the code is reproduced verbatim. Confidence is low on anything beyond that: real-world behaviour on large codebases, the undemonstrated ORM and i18n generators, error-reporting quality, and any adoption. One self-interested publisher plus a body that is truncated mid-sentence holds the overall figure just under halfway.
build
Your meter now runs on someone else's machine: signed receipts, fsync, and failing open1 distinct publisher
build
A Timed-Out Reset SMS Is Not A Failed One, And Your Retry Code Probably Disagrees1 distinct publisher
build
Buy transactional email on recovery controls, not send price1 distinct publisher
build
Count invalid JSON as a failed classification, and model choice becomes a reliability problem1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 16, 2026