npx skills add ...
npx skills add tomlord1122/tomtom-skill --skill 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.
npx skills add tomlord1122/tomtom-skill --skill golang-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.
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:
internal/ package and interface system are Go's primary architectural tools — use them before reaching for frameworks.Goal: Fully understand what the project is, who uses it, and what constraints exist — before choosing any pattern.
Key Questions to Ask:
Actions:
Decision Point: You can articulate:
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:
Anti-patterns:
Decision Point: Select and justify:
Goal: Design the Go module structure — the most important architectural decision in any Go project.
Thinking Framework — Go Package Principles:
user/ not models/, handlers/, services/.internal/ is your architectural boundary. Code in internal/ cannot be imported by external consumers.main.go thin. It wires things together (dependency injection); it contains no logic.Project Structure Templates:
Simple CLI:
Medium Service:
Library / SDK:
Operator / Controller:
Decision Point: The user can answer:
Goal: Design the dependency graph so the system is testable, composable, and changeable.
Thinking Framework — The Dependency Rule:
Go Interface Guidelines:
Dependency Injection in Go (no framework needed):
Goal: Design consistent, informative error handling across layers.
Thinking Framework:
Error Propagation Model:
Go Error Patterns:
Goal: Design for testability from the start — not as an afterthought.
Testing by Project Type:
| Project Type | Unit Tests | Integration Tests | E2E Tests |
|---|---|---|---|
| CLI tool | Core logic functions | Command execution with fixtures | Full binary invocation |
| HTTP service | Service layer with mocked deps | Repository with test DB | HTTP client against test server |
| Library | Public API behavior | N/A | Consumer-perspective tests |
| Operator | Reconciler logic | envtest with fake API server | Kind cluster tests |
Go Testing Principles:
testdata/ directory for fixtures_test.go in the same package for white-box tests, _test package for black-boxt.Parallel() for independent testst.Helper() in test utilitiesgo test -race in CI alwaysGoal: Ensure the project is ready for real-world use.
Production Checklist (applicable to all Go project types):
context.Context for cancellation-ldflags)go vet, staticcheck, go test -race, golangci-lintGoal: Provide a clear order of implementation.
General Sequence (adapt per project type):
go.modmain.goArguments:
project-dir - Project directory (default: current directory)db-engine - Database engine: postgresql, mysql, sqlite3 (default: postgresql)Examples:
Context7 Library ID: /websites/gin-gonic_en (117 snippets, Score: 90.8)
Official Documentation:
https://go.dev/doc/https://go.dev/doc/effective_gohttps://gin-gonic.com/en/docs/https://docs.sqlc.dev/https://cobra.dev/https://pkg.go.dev/sigs.k8s.io/controller-runtimeWhen providing Go architecture solutions:
"sqlc generate fails"
sqlc vet for detailed errors"Circular import"
"Too many packages"
"Context cancelled"
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.modmyoperator/
├── cmd/
│ └── controller/
│ └── main.go
├── api/
│ └── v1/
│ └── types.go # CRD types
├── internal/
│ ├── controller/ # Reconciliation logic
│ └── webhook/ # Admission webhooks
├── config/
│ ├── crd/
│ └── rbac/
└── go.mod// 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)
}// 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)
}External interface (HTTP/gRPC/CLI): User-facing messages + status codes
↑ transforms
Business logic layer: Domain-specific errors (NotFound, Conflict, Validation)
↑ wraps with context
Data/infrastructure layer: Infrastructure errors (DB timeout, network failure)// Sentinel errors for expected conditions
var ErrNotFound = errors.New("not found")
var ErrConflict = errors.New("conflict")
// Wrapping for context
return fmt.Errorf("getting user %s: %w", id, err)
// Checking with errors.Is / errors.As
if errors.Is(err, ErrNotFound) {
// handle not found
}bash /mnt/skills/user/golang-architect/scripts/sqlc-init.sh [project-dir] [db-engine]bash /mnt/skills/user/golang-architect/scripts/sqlc-init.sh
bash /mnt/skills/user/golang-architect/scripts/sqlc-init.sh ./my-project postgresql