Go 1.27.3 architectural standards — memory-aligned structs, typed enums, interface design, goroutine safety, iterators, idiomatic errors, sqlx + //go:embed SQL pattern, go.work multi-module layout, and the two app-repo shapes for a Go module with a SPA (module at the root + web/, or backend/ + frontend/, module path, cmd/internal pairing). Use when writing, reviewing, or scaffolding Go code, or deciding where a Go module and its frontend live in a repo.
Installs into .claude/skills of the current project.
Sponsors
SSkills DirectorySkills Directory
Know which skills are safe — weekly.
SSkills DirectorySkills Directory
Is that skill safe to install?
Are you the author of Go Architect?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/ralvarezdev-go-architect)
---
name: go-architect
version: 1.16.0
description: Go 1.27.3 architectural standards — memory-aligned structs, typed enums, interface design, goroutine safety, iterators, idiomatic errors, sqlx + //go:embed SQL pattern, go.work multi-module layout, and the two app-repo shapes for a Go module with a SPA (module at the root + web/, or backend/ + frontend/, module path, cmd/internal pairing). Use when writing, reviewing, or scaffolding Go code, or deciding where a Go module and its frontend live in a repo.
---
# Go Architecture & Domain Modeling
Targets **Go 1.27.3**. See [STACK.md](STACK.md) for pinned dependency versions.
## 1. Constants & Enums
- **Enums:** Custom types with `iota` and an implemented `String()` method. Avoid bare primitives. Use `1 << iota` for bitmasks.
- **Errors:** Export package-level sentinel errors (`var ErrNotFound = ...`) for `errors.Is()`. Use `errors.Join` to aggregate multiple errors.
- **Grouping:** When a file declares multiple `type`, `const`, or `var` at package level, consolidate each kind into a single parenthesized block (`type (...)`, `const (...)`, `var (...)`) rather than repeating the keyword. Keep unrelated groups separated by a blank line inside the block.
- **File-level ordering:** type → const → var → func (decorder's default order). Enforced by the `decorder` linter (see §14).
- **Magic values:** a bare numeric or string literal used more than once becomes a named constant. Enforced by `mnd` (numbers) and `goconst` (strings) (see §14).
## 2. Structures & Memory
- **Design:** Explicit struct tags, standard audit fields, composition via embedding. Keep tag casing (`json`, `yaml`) consistent across the codebase — `tagliatelle` catches drift, opt-in and scoped since legacy tags often can't be renamed without a breaking change (see §14).
- **Optimization:** Order fields largest → smallest to minimize padding.
- **Semantics:** Pointers for mutation or mutex-protected state; values for small, immutable payloads.
- **Validation:** `Validate() error` for structs taking external input; tag-based validation via `go-playground/validator`.
- **Ordering:** Use `cmp` (`cmp.Compare[T]`, `cmp.Or`, `cmp.Less`) as the default ordering toolkit.
- **Typed models over maps:** Prefer a defined struct to `map[string]any`/`map[string]interface{}` for shaped data — the compiler catches typos and missing fields a map silently swallows. `forbidigo` flags the anti-pattern (see §14); `exhaustruct` (opt-in, scoped to specific structs) catches incomplete struct literals once you've made the switch.
## 3. Instantiation
- **Constructors:** Always provide `New...` to initialize maps, slices, channels safely.
- **Configuration:** Functional Options pattern for complex setup; never large config structs passed by value.
## 4. Interfaces
- **Design:** Define interfaces where they're *used*, not where implemented. Keep them small (1–3 methods) — enforced by `interfacebloat` (see §14).
- **Signatures:** Accept interfaces (for easy mocking); return concrete structs — enforced by `ireturn` (see §14).
- **No anonymous interfaces:** an interface written inline (`x.(interface{ Policy() Policy })`, a parameter, a struct field) has no name to document, reuse, or grep, and the capability it describes never appears in the package's API. Declare `type PolicyProvider interface { Policy() Policy }` next to its consumer (or where the capability lives) and assert that. `interface{}`/`any` in a genuinely unconstrained position is fine; the smell is a *capability* left unnamed. Check with [`assets/check-no-anonymous-interfaces.sh`](assets/check-no-anonymous-interfaces.sh) — AST-based, skips generated code, `-tests` to include tests (see §14).
- **Wrapping an external program or SDK** (a CLI run as a subprocess, a vendor library): the domain owns the request and result types and a one-method port; the adapter is an anti-corruption layer, so the vendor's flags, files and structs never cross its edge. Have it *report* through an event sink instead of the caller scanning output afterwards, carry a cancel's who and why in `context.WithCancelCause`, give the port a second in-process fake adapter (a fake is the second adapter that makes the seam real), and run one conformance suite against every adapter. Pin the vendor's output formats with golden fixtures of real output at the adapter's edge. Don't add a port per concept (a "grader", a "scorer") until a second implementation exists. Worked code: [RECIPES.md](RECIPES.md#an-external-program-behind-a-port).
## 5. Stdlib defaults
Prefer stdlib over hand-rolled or third-party when stdlib now covers it.
- `slices`, `maps` — collection helpers (`Sort`, `Contains`, `Index`, `Clone`, `Equal`, `Concat`, etc.)
- `cmp` — `Compare`, `Less`, `Or`, `Ordered` — the default ordering toolkit.
- `iter` — `iter.Seq[T]`, `iter.Seq2[K,V]` for sequence-shaped returns (see §6).
- `log/slog` — structured logging; **default for new code**. Reach for `zap`/`zerolog` only when slog's allocator perf is provably insufficient.
- `errors` — `errors.Is`, `errors.As`, `errors.Join`.
- `net.JoinHostPort` / `net.SplitHostPort` — idiomatic host:port assembly (enforced by `nosprintfhostport` linter). Never `fmt.Sprintf("%s:%d", host, port)`.
## 6. Iterators (Go 1.23+)
- **Range-over-func:** `for x := range seq { ... }` where `seq` is `iter.Seq[T]`.
- **Return `iter.Seq[T]` when:** the sequence is large/unknown-size, consumer might short-circuit, or it's backed by an underlying cursor (DB pagination, HTTP pages).
- **Return `[]T` when:** the result is small, bounded, and the caller almost always wants the whole thing.
- **Anti-pattern:** wrapping a `[]T` in `slices.Values` just to look modern. Round-tripping back to `slices.Collect` is wasted ceremony.
## 7. Concurrency
- **State:** Embed `sync.RWMutex` directly above the fields it protects. `sync/atomic` for simple counters.
- **Context fields:** Never embed `context.Context` in structs (`containedctx` linter enforces this). Pass it as a parameter; contexts are designed as function arguments, not persistent state.
- **Duration:** Use `time.Duration` primitives; never multiply durations (`durationcheck` catches `time.Second * 60` — use `time.Minute` instead).
- **Context nesting:** Avoid nested contexts in loops or closures (`fatcontext` catches this anti-pattern).
- **WaitGroup:** Use `sync.WaitGroup.Go(fn)` (Go 1.25+) — replaces `Add(1) / go func() { defer Done(); ... }()` boilerplate.
- **Context:** Pass `context.Context` as the first parameter for any blocking or I/O. Use `signal.NotifyContext` for shutdown; the cancellation cause now records which signal fired (Go 1.26).
- **Containers:** `GOMAXPROCS` respects cgroup CPU limits since Go 1.25 — don't hardcode in containerized deploys.
## 8. Errors & Panics
- **Checking:** `errors.As` for custom types; `errors.Is` for sentinels. Never force type assertions on error results — use `ok` check or `errors.As` (`forcetypeassert` enforces this).
- **Aggregation:** `errors.Join(errs...)` when collecting multiple errors (validation, parallel fan-out).
- **Wrapping:** `fmt.Errorf("op: %w", err)` to add context while preserving the chain. When wrapping external package errors, use `wrapcheck` to verify proper context addition (prevents "swallowing" errors).
- **Panics:** Restrict to initialization (`MustCompile` style). Never as control flow.
## 9. Testing
- **Patterns:** Table-driven tests and black-box testing (`package mypkg_test`). Parallelize tests with `t.Parallel()` — checked and enforced by `paralleltest` and `tparallel` linters. Avoid deprecated testing APIs (`ioutil.TempDir` → `t.TempDir()`); `usetesting` enforces modern stdlib testing functions.
- **Helpers:** `t.Helper()` as the first line in any custom assertion — enforced by `thelper`.
- **Concurrent code:** Use `testing/synctest` (GA in Go 1.25) — virtualizes time, waits for goroutines to quiesce, makes async tests deterministic.
- **Library:** `stretchr/testify` for assertions/mocks/suites when stdlib alone is awkward. Use `testifylint` to catch incorrect assertion patterns (`assert` vs `require`).
- **Integration tests against Docker dependencies:** `testcontainers-go` — spins up real Postgres/Redis/Kafka/etc. containers per test run instead of mocking the driver or relying on a shared dev instance. Gate behind a build tag (e.g. `//go:build integration`) or `testing.Short()` check so `go test ./...` stays fast by default.
## 10. Packages
- **Naming:** Short, lowercase, single-word. Never `util`, `common`, `helpers`.
- **Layout:** Organize by domain/feature, not by technical layer.
- **Directory = package.** Splitting a package to hit a file count changes the import path, package name, and exported surface — split on a real seam, not on size. Many well-named files in one package is normal (`net/http`, `go/types`); the folder's navigability, not the count, is the trigger. See [code-design-refactor §4](../../refactoring/code-design-refactor/SKILL.md#4-extract).
- **Domain modeling & interface placement:** See [hexagonal-arch](../../design/hexagonal-arch/SKILL.md) for ports/adapters and [ddd-architect](../../design/ddd-architect/SKILL.md) for aggregates/bounded contexts. For `go.work` multi-module layout, see §16.
## 11. Dependencies & Logging
- **Injection:** Pass dependencies via constructors. No global state, no package `init()` setups. For larger graphs use `uber-go/fx` or `google/wire`.
- **The container lives at the composition root, never in a library.** A library exposes `New(deps...)` and never imports `fx`/`wire` — doing so drags the container into every consumer. When a graph is large, the *deployable* owns the container (`app/`, `internal/bootstrap`, `cmd/`); libraries stay constructor-only. Optional courtesy for `fx` users: ship an `fx.Module` in a dedicated subpackage (`<pkg>/fxmod`) that groups the `fx.Provide`s for the library's constructors — whoever uses `fx` includes it, whoever doesn't calls `New` by hand, and the library stays DI-agnostic.
- **Ports and constructors live in the packages; the container lives at the edge.** The rest of the code sees only interfaces — the DI framework never leaks past the composition root (see [hexagonal-arch §2](../../design/hexagonal-arch/SKILL.md#2-dependency-direction--always-inward)).
- **Config:** `spf13/viper` for layered env + file + flag configuration.
- **Logging:** `log/slog` (stdlib), see §5. Structured, context-aware.
## 12. Database access — sqlc (default), sqlx + `//go:embed` (alternative)
**Default: `sqlc`.** Schema-first, code-generated queries — write named queries in `.sql` files against your real migrated schema, run `sqlc generate`, get back typed Go row structs and query methods, checked at generate-time against the actual database. No ORM magic, no hand-written scanning code, queries stay plain auditable SQL in git.
Examples (query file, `sqlc.yaml`, repo method, layout): [RECIPES.md](RECIPES.md#sqlc-default).
- **Migrations:** `goose` or `golang-migrate` — versioned up/down pairs in `migrations/`. `sqlc`'s `schema:` reads the same migration files, so schema drift between the two is impossible by construction.
- **Regeneration:** run `sqlc generate` in CI (or a pre-commit hook) and fail the build if the generated tree differs from what's committed — generated code is committed, not built on the fly.
**Alternative: `jmoiron/sqlx` + `//go:embed`.** Reach for this when a query needs genuine runtime composition sqlc's static named-query model can't express (e.g. an arbitrary number of optional filter clauses), or when a package deliberately avoids a codegen step. Write raw SQL in `.sql` files, embed at compile time, execute via `sqlx`'s struct-tag scanning. Example and layout: [RECIPES.md](RECIPES.md#sqlx--goembed-alternative).
- **Dynamic queries:** even here, write the static fragments in `.sql` files and join them in Go rather than building SQL by string concatenation against user input — always use parameter binding.
- Don't mix the two within one repository package — pick per-package, not per-query, so a reader knows which scanning convention to expect from the file layout alone.
## 13. Generics
- **Usage:** Data structures and utility functions only. If an interface would serve, prefer it.
- **Self-referential constraints (Go 1.26):** `type Adder[A Adder[A]] interface { Add(A) A }` is valid — useful for fluent-style domain types.
- **Type aliases with type params (Go 1.24):** `type IntMap[V any] = map[int]V`.
## 14. Tooling
- **Lint:** `golangci-lint` **v2** — a single binary that aggregates `staticcheck`, `govet`, `gofmt`, `goimports`, `revive`, and dozens more. Pin via `.golangci.yml` (v2 config schema). Run on every commit and in CI. Treat warnings as errors. Drop-in template: [`assets/golangci.yml`](assets/golangci.yml) — copy to your project root as `.golangci.yml` and set `goimports.local-prefixes` to your module path.
- **Essential linters:** `govet`, `staticcheck`, `unused`, `gocritic`, `revive`, `errorlint`, `gosec`, `misspell`, `sloglint`, `godoclint`.
- **Code quality:** `nolintlint` validates that `//nolint` directives are specific and actually suppress something — enforces intentional, clean ignores. `varnamelen` enforces minimum variable name length (catches `x`, `i` outside loops; configure `max-distance: 5, min-name-length: 1`). `errname` ensures error types follow convention (`ErrFoo`, `FooError`) — complements §1's sentinel error pattern.
- **Idiomatic patterns:** `prealloc` detects slices that could pre-allocate capacity — idiomatic Go performance practice. `reassign` flags package variable reassignment in favor of const/new-var idiom. `makezero` catches unintended zero-length slice declarations. `predeclared` prevents shadowing Go builtins. `recvcheck` ensures method receiver types are consistent within an interface. `dogsled` flags excessive blank identifiers (e.g., `_, _, _, v := ...` suggests destructuring instead). `mirror` catches bytes/strings type mismatches (e.g., comparing `[]byte` to `string` idiomatically). `exptostd` replaces `golang.org/x/exp` packages with stdlib equivalents — use stdlib for idiomatic Go. `modernize` suggests modern Go simplifications (range-over-int, slices API, etc.).
- **Duplication & magic values:** `dupl` (structural clones), `goconst` (repeated string literals), `mnd` (magic numbers) — all push toward named constants/enums (see §1).
- **Complexity & size:** `nestif`, `gocognit` (cognitive complexity), `maintidx` (maintainability index), plus revive's `file-length-limit` and `argument-limit` rules — catch functions/files that should be split before they rot.
- **Declaration structure:** `decorder` enforces file-level `type → const → var → func` ordering (decorder's default). Set `disable-dec-order-check: false` in your `.golangci.yml` to enable (see §1). `gochecknoinits` flags `init()` outright (see §11).
- **Interfaces & enums:** `interfacebloat` caps interface method count, `ireturn` enforces concrete returns (see §4); `exhaustive` forces enum-typed `switch` statements to cover every value; `forbidigo` bans `map[string]interface{}`/`map[string]any` in favor of typed structs (see §2) — requires careful regex tuning for your codebase (consider enforcing struct typing via code review if regex patterns get unwieldy; template includes reference patterns in `assets/forbidigo-patterns.yml`).
- **modernize** (standalone linter, golangci-lint v1.57+): all checks on by default — catches `range n` (Go 1.22+), `slices.Sort`, `slices.Contains`, `maps.Keys`, `maps.Values`, etc. If too noisy, constrain via `modernize.settings` (e.g., `forRangeInts: true` only).
- **intrange** (standalone linter): explicitly enabled — flags `for i := 0; i < n; i++` where `range n` is cleaner. Lightweight alternative to the `modernize` coverage.
- **copyloopvar** / **perfsprint**: modernization nudges — `copyloopvar` flags now-redundant `x := x` loop-variable copies (Go 1.22+ semantics), `perfsprint` suggests faster alternatives to `fmt.Sprintf`/`fmt.Errorf` (e.g. `strconv`, `err.Error()`). Both low-noise, safe to enable by default.
- **Optional: Scoped Linters** (enable when appropriate for your project):
- `depguard`: Controls allowed imports (e.g., no test frameworks in prod code). Requires careful allowlist configuration per project structure — enable after establishing import boundaries.
- **Cleanup & ordering:**
- `unparam`: Reports unused function parameters — aids cleanup (can be noisy during refactoring).
- `funcorder`: Enforces consistent function/method/constructor ordering within types.
- **Template:** The [`assets/golangci.yml`](assets/golangci.yml) template includes sane defaults for all recommended linters with tested configuration values for `linters.settings`. Copy it to `.golangci.yml` and customize thresholds (e.g., `gocognit.max` for cognitive complexity) to match your project's complexity profile.
- **Dead code (`deadcode`, opt-in, not golangci-lint):** `unused` only flags unused *unexported* symbols, so an exported function no `main` reaches passes the lint gate forever. Run `deadcode -test ./...` (`golang.org/x/tools/cmd/deadcode`) so tests count as roots — without `-test` every test helper looks dead. It does not follow dynamic dispatch (cobra `RunE`, handler funcs stored in maps), so confirm each hit before deleting. Re-run after a deletion pass: removing one function can be the last use of another. Wire it into its own task target rather than the lint gate, since it needs a `main` to root from. For a shared library with several consumers, run it per consumer with `-filter` and cross-check with `go list -deps`; see [codebase-hygiene-reviewer](../../quality/codebase-hygiene-reviewer/SKILL.md).
- **Doc-comment coverage (opt-in):** the main config disables revive's `exported`/`package-comments` rules — doc coverage isn't part of the standard gate (see §15). Run it on demand with the secondary config [`assets/golangci.doccheck.yml`](assets/golangci.doccheck.yml): `golangci-lint run -c golangci.doccheck.yml ./...`.
- **Repo-level style guards (opt-in, not golangci-lint):** three conventions golangci-lint has no linter for — no one-line function bodies, no decorative separator comments (`// ──`, `# ═══`), no anonymous interfaces (see §4; `interfacebloat` and `ireturn` count methods, they do not ask for a name). Ship as scripts, not lint rules, since existing codebases likely have violations needing a separate cleanup pass first: [`assets/check-no-oneline-functions.sh`](assets/check-no-oneline-functions.sh), [`assets/check-no-separator-comments.sh`](assets/check-no-separator-comments.sh), [`assets/check-no-anonymous-interfaces.sh`](assets/check-no-anonymous-interfaces.sh) (this one is a `go/ast` walker, because a grep cannot tell `type X interface` from an inline one). Wire each into its own task-runner target (see `repo-tooling-architect` §4 for Task/just setup) rather than the main lint gate, so a legacy-codebase failure doesn't block unrelated CI.
- **Modernization:** Run `go fix` periodically (revamped in Go 1.26 as push-button modernizers). It rewrites legacy patterns toward current stdlib APIs and respects `//go:fix inline` directives for local refactors. Ongoing hygiene, not a one-off.
- **Format:** `gofmt` (built-in) plus `goimports` (via `golangci-lint`) — no other formatter, no debate.
- **Build/run:** `go build`, `go test`, `go vet`, `go work` for multi-module repos. Stdlib only — avoid Make/Task wrappers unless multi-language CI demands it.
## 15. Documentation
- **Format:** Exported names get full-sentence comments starting with the identifier name. Include a package-level comment.
- **Style:** Weave parameter and return names into prose (no `@param`). Document specific error conditions.
- **Focus:** Explain *why* (business rules, edge cases) — code already shows *what*.
## 16. Multi-module workspaces (`go.work`)
For repos where `go.work` ties together independently-versioned modules — one per bounded context, plus shared libraries — rather than a single `go.mod`.
- **Module boundary is the real privacy/reuse unit.** Once something is its own module (own `go.mod`), nesting it under a directory named `internal/` adds nothing — Go's `internal/` import restriction is a single-module-tree mechanism and does nothing extra for something already module-isolated. Treat the directory name as organizational labeling, not enforcement. If a service module needs a genuine internal-only boundary, nest a further `internal/` inside that module (`internal/order/internal/wire/`).
- **`pkg/*`** — each subdirectory its own module, for code genuinely shared by 2+ service modules (validation, observability, an RFC 9457 problem-detail mapper). Don't default to creating `pkg/`; per [hexagonal-arch §7](../../design/hexagonal-arch/SKILL.md#7-when-not-to-use-it), a shared seam is only real once two consumers need it.
- **Root-level `domain`** — only for value objects/types genuinely shared *across* bounded contexts (e.g. a `Money` type used by both Order and Payment). Most contexts should keep their domain private inside their own service module. A shared root `domain` module is a deliberate Shared Kernel (see [ddd-architect's context-mapping table](../../design/ddd-architect/PATTERNS.md#1-context-mapping-patterns)), not a default.
- **`internal/<service>`** — one bounded context = one module. Internally structured per [hexagonal-arch](../../design/hexagonal-arch/SKILL.md): `domain/`, `app/`, `adapters/{primary,secondary}` — or flatter, since hexagonal-arch mandates the dependency direction, not the folder split. "Service" here means the deployable module itself, not [ddd-architect's Domain/Application Service patterns](../../design/ddd-architect/SKILL.md#7-domain-vs-application-services) — a single `internal/<service>` module typically contains several Application Services inside its `app/` layer (e.g. `PlaceOrderService`).
- **`cmd/<service>` vs `internal/<service>`** — keep distinct rather than merging composition into `cmd`. `cmd/<service>/main.go` stays minimal: parse flags/env, wire `signal.NotifyContext`, call into `internal/<service>`, handle the exit code. `internal/<service>` is the actual composition root — DI graph, adapter wiring, server lifecycle — so it's exercisable independently of process-level concerns.
- **Cross-context calls never reach into another context's `domain/` or `adapters/`.** They go through that context's public API (HTTP/gRPC, since each service is a separate deployable in a multi-module workspace). The calling context defines its *own* ports shaped for what it needs (`OrderCreator`, not `order.Repository`) — the same "define interfaces where used" rule from §4, applied across a context boundary. This is the Go-flavored version of [ddd-architect's Customer/Supplier or Open Host Service patterns](../../design/ddd-architect/PATTERNS.md#1-context-mapping-patterns).
- **Scaling past a handful of contexts** — grouping, flat-by-default features, the rank rule and what large Go projects do: see §17.
- **Full worked example** — an order-owning service plus a checkout orchestrator service, with code — lives in [RECIPES.md](RECIPES.md).
## 17. Layout at scale (large repos)
§16 is the default. For a repo that has outgrown it, **there is no single correct layout — only better fits for a project's shape.** [LAYOUTS.md](LAYOUTS.md) is the catalogue (library, flat by concept, feature-first, escalated, grouped at the root, multi-module, layer-first), each with its trade-off, plus sections on module count, process types, generated code, cross-context communication, tests, ownership and layout smells, and a per-project review checklist. Review it per project and re-review when contexts, binaries or teams change.
Principles that hold across them:
- **Default to the lightest layout that fits.** Feature/context first, flat by default; escalate to `core/` + use cases + `adapters/<tech>/` only when a feature is domain-heavy.
- **Implementations are sibling subpackages named by technology**; interfaces are declared next to their consumer.
- **Enforce the dependency direction with a test**, not prose — see [LAYOUTS.md cross-cutting rules](LAYOUTS.md#cross-cutting-rules-all-layouts).
- **Group contexts at the root by area** (not a generic `contexts/`) past ~7; extract a group as a module past ~8–10 or with its own team.
- **No infrastructure in the model; wire schemas in `contracts/`; no stutter; name the composition root for what it is, not `app`.**
- **Layer-first (`core/<ctx>`, `services/<ctx>`, `adapters/<ctx>`) is a valid but suggestive option** — it trades context extractability for a trivial rank rule.
- **App repo with a SPA: two shapes, pick one per repo and record it.** (A) the module at the repo root with the SPA in `web/`, the ecosystem majority; (B) `backend/` with a sibling `frontend/`, for monorepos where the SPA is the product. Both: the module path names the directory that holds `go.mod`, one composition root per binary with a wiring-only `main.go`, operational dirs (`config/`, `bin/`, `scripts/`) only at the root, `go.work` only for real second modules (never a single `use .`), binaries named for the process, and a `.gitkeep` for every directory an embed or a bind mount needs. Trees, the choice table, the frontend-directory naming rule and the embed routes are in [LAYOUTS.md](LAYOUTS.md#app-repo-with-a-spa--two-shapes).
- **An adapter never imports another adapter's SDK** — a REST client shared with a CLI must not pull the MCP SDK for a helper; the caller owns credential resolution.
## Canonical libraries
See [STACK.md](STACK.md) for the full pinned list — viper, validator, cobra/pflag, gin, sqlx, grpc, protobuf-go, testify, fx, golang-migrate, buf.