Project Structure
Project Structure
Section titled “Project Structure”goctl generates a consistent directory layout for every project. Understanding it is the fastest way to be productive in any go-zero codebase.
API Service
Section titled “API Service”Generated by goctl api go -api user.api -dir .:
user-api/├── etc/│ └── user-api.yaml # Runtime config (host, port, DB, RPC endpoints)├── internal/│ ├── config/│ │ └── config.go # Typed config struct that maps to the YAML│ ├── handler/│ │ ├── routes.go # Auto-generated route registration│ │ └── loginhandler.go # One file per @handler — binds request, calls logic│ ├── logic/│ │ └── loginlogic.go # Business logic — the only file you normally edit│ ├── svc/│ │ └── servicecontext.go # Shared deps: DB pool, RPC clients, Redis, etc.│ └── types/│ └── types.go # Auto-generated request/response structs└── user-api.go # main() — starts rest.ServerRPC Service
Section titled “RPC Service”Generated by goctl rpc protoc user.proto --zrpc_out=.:
user-rpc/├── etc/│ └── user-rpc.yaml # ListenOn, Etcd registration, DB config├── internal/│ ├── config/│ │ └── config.go│ ├── logic/│ │ └── getuserlogic.go # One file per RPC method│ ├── server/│ │ └── userserver.go # gRPC server impl — delegates to logic layer│ └── svc/│ └── servicecontext.go├── pb/│ └── user/ # protoc-generated .pb.go and _grpc.pb.go├── userclient/│ └── user.go # go-zero generated type-safe client wrapper└── user.go # main() — starts zrpc.ServerLayer Responsibilities
Section titled “Layer Responsibilities”| Layer | Package | Responsibility | Contains business logic? |
|---|---|---|---|
| Handler | internal/handler | Parse & validate HTTP request, call logic, write response | No |
| Logic | internal/logic | Implement use-case; orchestrate DB/cache/RPC calls | Yes |
| ServiceContext | internal/svc | Construct and hold shared dependencies once at startup | No |
| Config | internal/config | Map YAML fields to typed Go structs | No |
| Model | internal/model | Data access layer (generated by goctl model) | No |
Multi-Service Project Layout
Section titled “Multi-Service Project Layout”For repositories with multiple services, the standard convention is:
project-root/├── service/│ ├── user/│ │ ├── api/ # user-api│ │ └── rpc/ # user-rpc│ ├── order/│ │ ├── api/│ │ └── rpc/│ └── payment/│ └── rpc/├── common/ # Shared utilities (errors, middleware, etc.)└── deploy/ ├── docker-compose.yaml └── k8s/Recommended Practices
Section titled “Recommended Practices”- Thin handlers — a handler should do nothing except decode the request, call one logic method, and encode the response.
- One logic file per use case —
CreateOrderLogic,GetOrderLogic,CancelOrderLogicare separate files, even if the methods are small. - ServiceContext is the only constructor — never call
sql.Openorredis.NewClientoutsidesvc.NewServiceContext. - Config over code — every tunable value (timeouts, feature flags, downstream addresses) belongs in
etc/*.yaml, not hardcoded. - Model layer is generated, logic layer is yours — regenerate models freely; the logic layer is where your business code lives and is never overwritten by goctl.