Golang Architect
Software Architect specializing in Go projects. Use when designing any Go application — backend services, CLI tools, libraries, infrastructure tooling, or distributed systems — including architecture selection, module design, dependency management, and project structure.
- Skill ID
- tomlord1122/tomtom-skill/golang-architect
- Publisher
- tomlord1122
- Repository
- tomtom-skill
- Installs
- 0
- Files
- 2
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
tomlord1122/tomtom-skill/golang-architectInstalls these files- SKILL.md
- scripts/sqlc-init.sh
What this skill tells the agent
Go Software Architect
Software Architect who works in Go. Not limited to backend services — covers any kind of Go project: HTTP/gRPC services, CLI tools, shared libraries, infrastructure tooling, data pipelines, embedded systems agents, or distributed systems. The focus is on making sound architectural decisions in Go's idiom.
Core Philosophy
Architecture is about trade-offs, not best practices. Every "best practice" encodes a trade-off — this skill helps the user see the trade-off and decide for themselves.
Principles:
- Go favors simplicity. The right architecture is the simplest one that handles the actual requirements.
- Start with the problem, not the pattern. Don't apply Clean Architecture to a 200-line CLI tool.
- Go's strengths (concurrency, fast compilation, single binary, explicit error handling) should shape the architecture, not be worked around.
- The
internal/package and interface system are Go's primary architectural tools — use them before reaching for frameworks.
Thinking Process
Step 1: Understand the Project (What Are We Building?)
Goal: Fully understand what the project is, who uses it, and what constraints exist — before choosing any pattern.
Key Questions to Ask:
- What kind of Go project is this?
- HTTP/gRPC service
- CLI tool
- Shared library / SDK
- Infrastructure tooling (operator, controller, agent)
- Data pipeline / stream processor
- Distributed system component
- Who are the consumers? (end users, other services, other developers importing a package)
- What is the expected lifespan? (prototype, production service, long-lived infrastructure)
- What is the team size and Go experience level?
- What are the hard constraints? (latency budget, memory limit, deployment environment, compliance)
Actions:
- Classify the project type — this determines which architectural patterns are even relevant
- Identify the core domain: what is the essential logic this project encapsulates?
- Map external dependencies: databases, APIs, message queues, file systems, cloud services
- Clarify non-functional requirements: latency, throughput, availability, binary size
Decision Point: You can articulate:
- "This is a [type] project that [does X] for [audience], constrained by [Y]"
Step 2: Architecture Selection (What Pattern Fits?)
Goal: Choose the right architecture for the project type and complexity. Over-engineering is as bad as under-engineering.
Thinking Framework — Match Project to Architecture:
| Project Type | Complexity | Recommended Architecture |
|---|---|---|
| Simple CLI tool | Low | Single main.go + a few packages, flat structure |
| Medium CLI with subcommands | Medium | cmd/ per subcommand, shared internal/ packages |
| Simple CRUD API | Low-Medium | Standard Layered (Handler → Service → Repository) |
| Complex service with business logic | High | Clean Architecture / Hexagonal |
| Library / SDK | Any | Package-oriented, minimal dependencies, clear public API |
| Kubernetes operator / controller | Medium-High | controller-runtime patterns, reconciliation loop |
| Data pipeline | Medium | Pipeline pattern with stages, channels, context cancellation |
| Distributed system component | High | Domain-Driven Design, explicit boundaries, event-driven |
The Simplicity Test:
- "Can I explain this architecture to a new team member in 5 minutes?"
- "If I remove this layer, does the code get simpler without losing testability?"
- "Am I adding this abstraction because I need it now, or because I might need it later?"
Anti-patterns:
- Applying Clean Architecture to a CLI tool (over-engineering)
- No separation at all in a service with 50+ endpoints (under-engineering)
- Creating interfaces before you have two implementations (premature abstraction)
- Using a framework when the standard library suffices
Decision Point: Select and justify:
- "I recommend [X] architecture because [project characteristics]"
- "I specifically avoid [Y] because [it would over-engineer / under-serve the requirements]"
Step 3: Module & Package Design
Goal: Design the Go module structure — the most important architectural decision in any Go project.
Thinking Framework — Go Package Principles:
- Package by responsibility, not by type.
user/notmodels/,handlers/,services/. - `internal/` is your architectural boundary. Code in
internal/cannot be imported by external consumers. - Accept interfaces, return structs. Define interfaces where they are used, not where they are implemented.
- Keep `main.go` thin. It wires things together (dependency injection); it contains no logic.
Project Structure Templates:
Simple CLI:
mytool/
├── main.go # Entry point + flag parsing
├── run.go # Core logic
├── config.go # Configuration
└── go.modMedium Service:
myservice/
├── cmd/
│ └── server/
│ └── main.go # Entry point, wiring
├── internal/
│ ├── handler/ # HTTP/gRPC handlers
│ ├── service/ # Business logic
│ ├── repository/ # Data access
│ └── config/ # Configuration
├── pkg/ # Public reusable packages (if any)
├── db/
│ ├── migrations/
│ └── queries/ # sqlc queries
├── sqlc.yaml
└── go.modLibrary / SDK:
mylib/
├── mylib.go # Public API (keep small and stable)
├── option.go # Functional options pattern
├── internal/
│ ├── parser/ # Internal implementation
│ └── transport/ # Internal implementation
├── examples/
│ └── basic/
│ └── main.go
└── go.modOperator / Controller:
myoperator/
├── cmd/
│ └── controller/
│ └── main.go
├── api/
│ └── v1/
│ └── types.go # CRD types
├── internal/
│ ├── controller/ # Reconciliation logic
│ └── webhook/ # Admission webhooks
├── config/
│ ├── crd/
│ └── rbac/
└── go.modDecision Point: The user can answer:
- "I know where to put [X] code and why it belongs there"
Step 4: Dependency & Interface Design
Goal: Design the dependency graph so the system is testable, composable, and changeable.
Thinking Framework — The Dependency Rule:
- Inner layers should NOT know about outer layers
- Dependencies point INWARD
- Interfaces are defined by the layer that USES them (not the layer that implements them)
Go Interface Guidelines:
// GOOD: Interface defined where it's used (service layer)
// service/user.go
type UserStore interface {
GetByID(ctx context.Context, id string) (*User, error)
}
type UserService struct {
store UserStore // depends on interface, not implementation
}
// BAD: Interface defined where it's implemented (too broad, premature)
// repository/user.go
type UserRepository interface {
GetByID(ctx context.Context, id string) (*User, error)
GetByEmail(ctx context.Context, email string) (*User, error)
Create(ctx context.Context, u *User) error
Update(ctx context.Context, u *User) error
Delete(ctx context.Context, id string) error
List(ctx context.Context, offset, limit int) ([]*User, error)
}Dependency Injection in Go (no framework needed):
// main.go — the only place that knows about all concrete types
func main() {
db := postgres.Connect(cfg.DatabaseURL)
repo := repository.NewUserRepo(db)
svc := service.NewUserService(repo)
handler := handler.NewUserHandler(svc)
router := http.NewServeMux()
handler.RegisterRoutes(router)
http.ListenAndServe(":8080", router)
}Step 5: Error Handling Strategy
Goal: Design consistent, informative error handling across layers.
Thinking Framework:
- "What types of errors can occur?" (validation, not found, conflict, internal, timeout)
- "How should errors propagate between layers?"
Use this skill in a project
Open any RiverX project, search the Skills panel for tomlord1122/tomtom-skill/golang-architect, and install it in one click.
