关于
This skill reviews Go project architecture, analyzing package structure, dependencies, layering, and module boundaries. It helps when designing layouts, evaluating dependency graphs, or refactoring monoliths into modules. Use it for architectural reviews but not for code style or API design, which have separate skills.
快速安装
Claude Code
推荐npx skills add eduardo-sl/go-agent-skills -a claude-code/plugin add https://github.com/eduardo-sl/go-agent-skillsgit clone https://github.com/eduardo-sl/go-agent-skills.git ~/.claude/skills/go-architecture-review在 Claude Code 中复制并粘贴此命令以安装该技能
技能文档
Go Architecture Review
Good architecture makes the next change easy. Bad architecture makes every change scary.
Operating Modes
Pick the mode that matches the request before starting:
- Layout review (default) — assess an existing codebase against the sections below and report violations with severity.
- Refactor plan — same assessment, but the deliverable is an ordered migration plan (smallest safe steps first), not just findings.
- New service consultation — asked "how should I structure X": apply sections 1-3 as prescriptive guidance instead of review checks.
Auditing Large Codebases
For repositories with many packages, build the dependency picture before judging it:
- Map the module:
go list ./...for packages, then import statements to trace dependency direction. - Run independent passes: (a) layout vs section 1, (b) dependency direction vs section 2, (c) wiring and config vs sections 3+5, (d) package design vs section 4.
- If your environment supports delegating work to parallel sub-agents or tasks, assign each pass to one; synthesize at the end — dependency findings often explain layout findings.
- Cite package paths and
file.go:linein every finding.
1. Standard Project Layout
myproject/
├── cmd/ # Main applications (one dir per binary)
│ ├── api-server/
│ │ └── main.go
│ └── worker/
│ └── main.go
├── internal/ # Private packages — cannot be imported externally
│ ├── domain/ # Core business types (entities, value objects)
│ │ ├── user.go
│ │ └── order.go
│ ├── service/ # Business logic (use cases)
│ │ ├── user.go
│ │ └── order.go
│ ├── store/ # Data access (repositories)
│ │ ├── postgres/
│ │ │ └── user.go
│ │ └── redis/
│ │ └── cache.go
│ ├── handler/ # HTTP/gRPC handlers (adapters)
│ │ └── user.go
│ └── config/ # Configuration loading
│ └── config.go
├── pkg/ # Public packages (use sparingly)
│ └── httputil/
│ └── response.go
├── migrations/ # Database migrations
├── api/ # API definitions (OpenAPI, proto files)
├── go.mod
├── go.sum
└── Makefile
Key Rules:
internal/enforces encapsulation at the compiler level. Use it aggressively.pkg/is for genuinely reusable packages. When in doubt, useinternal/.cmd/main packages should be thin — wire dependencies and callRun().- One
main.goper binary, minimal logic inside.
2. Dependency Direction
Dependencies MUST flow inward. Domain core has zero external dependencies:
handlers → services → domain ← stores
↓ ↓ ↓
(net/http) (pure Go) (database/sql)
Rules:
domain/imports NOTHING from the project. Nostore, nohandler, noconfig.service/depends ondomain/types and interfaces, NOT on concrete stores.handler/depends onservice/interfaces.store/implements interfaces defined inservice/ordomain/.- Circular dependencies are a 🔴 BLOCKER. The compiler catches them, but design should prevent them.
// ✅ Good — service defines the interface it needs
// internal/service/user.go
type UserStore interface {
GetByID(ctx context.Context, id string) (*domain.User, error)
Create(ctx context.Context, user *domain.User) error
}
type UserService struct {
store UserStore // depends on interface, not postgres.Store
}
// internal/store/postgres/user.go
type Store struct { db *sql.DB }
// Implements service.UserStore without importing the service package
func (s *Store) GetByID(ctx context.Context, id string) (*domain.User, error) { ... }
3. Main Package Wiring
main.go is the composition root. Wire everything here:
func main() {
cfg := config.Load()
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
db, err := sql.Open("postgres", cfg.DatabaseURL)
if err != nil {
logger.Error("connect db", slog.Any("error", err))
os.Exit(1)
}
defer db.Close()
// Wire dependencies
userStore := postgres.NewUserStore(db)
userService := service.NewUserService(userStore)
userHandler := handler.NewUserHandler(userService, logger)
// Setup router
r := chi.NewRouter()
r.Mount("/api/v1/users", userHandler.Routes())
// Run server
srv := &http.Server{Addr: cfg.Addr, Handler: r}
// ... graceful shutdown
}
Avoid dependency injection frameworks. Go's explicit wiring is a feature.
If wiring gets complex, use Google's wire for compile-time DI code generation.
4. Package Design Principles
One package = one purpose
// ✅ Good — clear purpose
package orderservice // business rules for orders
package postgres // PostgreSQL data access
package httphandler // HTTP transport layer
// ❌ Bad — grab-bag packages
package utils // what ISN'T a util?
package common // everything and nothing
package models // types without behavior
Avoid package stuttering
// ❌ Bad — package name repeated in type
package user
type UserService struct{} // user.UserService
// ✅ Good
package user
type Service struct{} // user.Service
Package cohesion over size
A package with 20 related files is better than 20 packages with 1 file each. Split packages when they have distinct responsibilities, not when they get big.
5. Configuration
type Config struct {
Addr string `env:"ADDR" envDefault:":8080"`
DatabaseURL string `env:"DATABASE_URL,required"`
LogLevel string `env:"LOG_LEVEL" envDefault:"info"`
Timeout time.Duration `env:"TIMEOUT" envDefault:"30s"`
}
Rules:
- All config from environment variables (12-factor).
- Validate at startup, fail fast with clear messages.
- No config scattered across packages — centralize in
internal/config. - Never hardcode values. Not even "just for now."
6. Init Functions
Avoid init(). It runs implicitly, makes testing harder, and creates hidden dependencies.
// ❌ Bad — hidden side effects
func init() {
db, _ = sql.Open("postgres", os.Getenv("DB_URL"))
}
// ✅ Good — explicit initialization
func NewStore(dsn string) (*Store, error) {
db, err := sql.Open("postgres", dsn)
if err != nil {
return nil, fmt.Errorf("open db: %w", err)
}
return &Store{db: db}, nil
}
Exception: registering drivers or codecs is acceptable in init():
func init() {
sql.Register("custom", &CustomDriver{})
}
Architecture Review Checklist
- 🔴 No circular dependencies between packages
- 🔴 Domain types have zero infrastructure dependencies
- 🔴 No business logic in
cmd/main packages - 🔴 No
init()with side effects (DB connections, HTTP calls) - 🟡
internal/used for project-private packages - 🟡 Interfaces defined at the consumer, not the producer
- 🟡 Configuration centralized and validated at startup
- 🟡 Dependency direction flows inward (handlers → services → domain)
- 🟢 Package names are short, singular, descriptive
- 🟢 No
utils/,common/,helpers/packages - 🟢 Main package is a thin composition root
GitHub 仓库
常见问题
什么是 go-architecture-review Skill?
go-architecture-review 是一个 Claude Skill,作者为 eduardo-sl。Skill 将 Claude 按需加载的说明和资源打包,让 Claude 无需额外提示即可执行与 go-architecture-review 相关的任务。
如何安装 go-architecture-review?
使用本页的安装命令:将 go-architecture-review 作为插件添加到 Claude Code,或将其仓库克隆到 skills 目录,然后重启 Claude 以加载该 Skill。
go-architecture-review 属于哪个分类?
go-architecture-review 属于设计分类。
go-architecture-review 可以免费使用吗?
可以。go-architecture-review 已收录在 AIMCP,可免费安装。
相关推荐技能
该Skill用于当开发者提供完整实施计划时,以受控批次方式执行代码实现。它会先审阅计划并提出疑问,然后分批次执行任务(默认每批3个任务),并在批次间暂停等待审查。关键特性包括分批次执行、内置检查点和架构师审查机制,确保复杂系统实现的可控性。
该Skill可在完成任务、实现主要功能或合并代码前自动调度代码审查子代理,确保实现符合需求和计划。它支持通过指定git SHA范围进行精准的代码变更审查,帮助开发者在关键节点及时发现潜在问题。核心原则是"早审查、勤审查",适用于开发流程的各个关键阶段。
这个Skill指导开发者如何将MCP服务器连接到Claude Code,支持HTTP、stdio和SSE三种传输协议。它涵盖了从安装配置到认证安全的完整流程,适用于集成GitHub、Notion、数据库等外部服务。当开发者需要添加集成、配置外部工具或提及MCP相关功能时,这个Skill能提供实用的操作指南。
该Skill帮助开发者根据任务特性选择Claude Code的Web或CLI界面,并指导如何在两种环境间无缝迁移会话。它能分析任务复杂度、迭代需求等要素,推荐最优工作界面和工作流。关键特性包括会话状态管理、环境切换指导和上下文优化建议。
