Learn / Go Service Engineering
Interfaces at Boundaries
Use interfaces where they describe ownership seams, not everywhere by habit.
Course: Go Service Engineering. Level: Intermediate. Topic: Reliable services.
Stage: intermediate - Intermediate package boundaries - Interfaces at service boundaries. Use interfaces where ownership changes hands: external APIs, persistence, queues, and tests.
Outcomes
- Keep interfaces small.
- Mock only external boundaries.
- Avoid package cycles.
Concepts
- consumer-owned interface
- adapter
- package boundary
- test double
Concept flow
Show how interfaces at service boundaries moves from trigger to implementation outcome in Go Services.
- Handler
- Service interface
- Adapter
- External API
Session flow
- Model consumer-owned interface (concept, 7 min) — Name the decisions behind consumer-owned interface before writing code.
- Keep interfaces small.
- Explain where consumer-owned interface belongs in ticket processing platform.
- Build the vertical slice (walkthrough, 13 min) — Implement the smallest useful slice in orders/service.go.
- Mock only external boundaries.
- Connect adapter to a working example.
- Verify and harden (exercise, 9 min) — Add a fake for a boundary test.
- Avoid package cycles.
- Record one risk or follow-up before moving on.
Code example
Go in orders/service.go.
package orders
import "context"
type PaymentGateway interface {
Charge(ctx context.Context, cents int64, token string) error
}
type Order struct {
PaymentToken string
totalCents int64
}
func (o Order) TotalCents() int64 {
return o.totalCents
}
type Service struct {
payments PaymentGateway
}
func (s Service) Checkout(ctx context.Context, order Order) error {
return s.payments.Charge(ctx, order.TotalCents(), order.PaymentToken)
}
Walkthrough examples
- Interfaces at Boundaries in a ticket processing platform — A team is extending a small Go service plus worker and needs this lesson's pattern to be clear enough for review, testing, and future maintenance.
- File: orders/service.go
- File: tests/interfaces-at-boundaries.spec
- File: docs/go-services/interfaces-at-boundaries.md
- Start from the provided Go snippet and make the intent visible in names and boundaries.
- Apply the checklist item "Find package owner" before adding extra behavior.
- Write down how the implementation changes when adapter fails or becomes slow.
Practice
- Shrink one interface to the methods a consumer needs.
- Move an adapter to infrastructure code.
- Add a fake for a boundary test.
Checklist
- Find package owner
- Trim interface methods
- Add adapter
- Write boundary test
Quiz prompts
- Where is a Go interface often most useful? — Consumer-owned interfaces describe what the caller needs without leaking implementation details.
- A teammate wants to hide consumer-owned interface inside a convenient helper. What should you check first? — Place consumer-owned interface at the boundary that keeps ticket processing platform behavior explicit, testable, and reviewable.
- Which artifact best proves this Go Services lesson is ready for review? — Production-ready learning needs evidence: a test, trace, command, screenshot, or log that catches the risk again.
- Intermediate package boundaries: a teammate says the happy path works, but "Consumer-owned interface" is still implicit. What should you ask for before merging? — Consumer-owned interface belongs in the intermediate stage only when the decision is visible, testable, and tied to a realistic failure mode.
- A reviewer has five minutes to evaluate this intermediate Go Services slice. Which evidence is strongest? — Refactor an intermediate Go service boundary with a consumer-owned interface, concrete adapter, and fake-backed behavior test.
Flashcards
- Intermediate package boundaries: what decision does "Consumer-owned interface" force you to make? Define the smallest capability the service needs instead of mirroring implementation structs. Evidence prompt: Shrink one interface to the two methods the service actually calls.
- Intermediate package boundaries: what decision does "Adapter placement" force you to make? Keep external clients and database adapters outside business packages. Evidence prompt: Move one concrete adapter behind a package boundary and update imports.
- Intermediate package boundaries: what decision does "Test double contract" force you to make? Use fakes to test business behavior without mocking every internal method call. Evidence prompt: Replace one over-broad mock with a fake that stores only observable behavior.
- In Go Services, what should you remember about consumer-owned interface? consumer-owned interface matters here because it supports "Keep interfaces small.".
- In Go Services, what should you remember about adapter? adapter matters here because it supports "Mock only external boundaries.".
- In Go Services, what should you remember about package boundary? package boundary matters here because it supports "Avoid package cycles.".
- In Go Services, what should you remember about test double? test double matters here because it supports "Keep interfaces small.".
Labs
- Ship a interfaces at boundaries slice — Extend a small Go service plus worker with a small but reviewable feature that proves the lesson's architecture in code.
- Refactor an intermediate Go service boundary with a consumer-owned interface, concrete adapter, and fake-backed behavior test.
- Shrink one interface to the two methods the service actually calls.
- Move one concrete adapter behind a package boundary and update imports.
- Replace one over-broad mock with a fake that stores only observable behavior.
- Shrink one interface to the methods a consumer needs.
- Move an adapter to infrastructure code.
- The lab demonstrates the intermediate package boundaries outcome without skipping earlier contract evidence.
- Each subtopic has a concrete artifact: Consumer-owned interface, Adapter placement, Test double contract.
- The review notes explain how this level changes ownership, verification, or operational risk.
Challenge
- Review-ready interfaces at boundaries (Core) — Refactor an intermediate Go service boundary with a consumer-owned interface, concrete adapter, and fake-backed behavior test.
- All checklist items are either implemented or documented with a reason.
- The change can be understood from orders/service.go plus one short note.
- The concept diagram names ownership, failure handling, and verification points.
- A teammate could run the verification steps without asking for hidden context.
Canonical lesson URL