encore-go-service
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEncore Go Service Structure
Encore Go 服务结构
Instructions
操作说明
In Encore Go, each package with an API endpoint is automatically a service. No special configuration needed.
在Encore Go中,每个包含API端点的包都会自动成为一个服务,无需额外配置。
Creating a Service
创建服务
Simply create a package with at least one endpoint:
//encore:apigo
// user/user.go
package user
import "context"
type User struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
}
//encore:api public method=GET path=/users/:id
func GetUser(ctx context.Context, params *GetUserParams) (*User, error) {
// This makes "user" a service
}只需创建一个包含至少一个端点的包即可:
//encore:apigo
// user/user.go
package user
import "context"
type User struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
}
//encore:api public method=GET path=/users/:id
func GetUser(ctx context.Context, params *GetUserParams) (*User, error) {
// 这会将"user"标记为一个服务
}Minimal Service Structure
最小服务结构
user/
├── user.go # API endpoints
├── db.go # Database (if needed)
└── migrations/ # SQL migrations
└── 1_create_users.up.sqluser/
├── user.go # API端点
├── db.go # 数据库(如有需要)
└── migrations/ # SQL迁移脚本
└── 1_create_users.up.sqlApplication Patterns
应用架构模式
Single Service (Recommended Start)
单服务(推荐入门方式)
Best for new projects - start simple, split later if needed:
my-app/
├── encore.app
├── go.mod
├── api.go # All endpoints
├── db.go # Database
└── migrations/
└── 1_initial.up.sql最适合新项目——从简单结构开始,必要时再拆分:
my-app/
├── encore.app
├── go.mod
├── api.go # 所有端点
├── db.go # 数据库
└── migrations/
└── 1_initial.up.sqlMulti-Service
多服务架构
For distributed systems with clear domain boundaries:
my-app/
├── encore.app
├── go.mod
├── user/
│ ├── user.go
│ ├── db.go
│ └── migrations/
├── order/
│ ├── order.go
│ ├── db.go
│ └── migrations/
└── notification/
└── notification.go适用于具有清晰领域边界的分布式系统:
my-app/
├── encore.app
├── go.mod
├── user/
│ ├── user.go
│ ├── db.go
│ └── migrations/
├── order/
│ ├── order.go
│ ├── db.go
│ └── migrations/
└── notification/
└── notification.goLarge Application (System-based)
大型应用(基于系统分组)
Group related services into systems:
my-app/
├── encore.app
├── go.mod
├── commerce/
│ ├── order/
│ │ └── order.go
│ ├── cart/
│ │ └── cart.go
│ └── payment/
│ └── payment.go
├── identity/
│ ├── user/
│ │ └── user.go
│ └── auth/
│ └── auth.go
└── comms/
├── email/
│ └── email.go
└── push/
└── push.go将相关服务按系统分组:
my-app/
├── encore.app
├── go.mod
├── commerce/
│ ├── order/
│ │ └── order.go
│ ├── cart/
│ │ └── cart.go
│ └── payment/
│ └── payment.go
├── identity/
│ ├── user/
│ │ └── user.go
│ └── auth/
│ └── auth.go
└── comms/
├── email/
│ └── email.go
└── push/
└── push.goService-to-Service Calls
服务间调用
Just import and call the function directly - Encore handles the RPC:
go
package order
import (
"context"
"myapp/user" // Import the user service
)
//encore:api auth method=GET path=/orders/:id
func GetOrderWithUser(ctx context.Context, params *GetOrderParams) (*OrderWithUser, error) {
order, err := getOrder(ctx, params.ID)
if err != nil {
return nil, err
}
// This becomes an RPC call - Encore handles it
orderUser, err := user.GetUser(ctx, &user.GetUserParams{ID: order.UserID})
if err != nil {
return nil, err
}
return &OrderWithUser{Order: order, User: orderUser}, nil
}只需直接导入并调用函数即可——Encore会自动处理RPC通信:
go
package order
import (
"context"
"myapp/user" // 导入user服务
)
//encore:api auth method=GET path=/orders/:id
func GetOrderWithUser(ctx context.Context, params *GetOrderParams) (*OrderWithUser, error) {
order, err := getOrder(ctx, params.ID)
if err != nil {
return nil, err
}
// 这会自动转为RPC调用——由Encore处理
orderUser, err := user.GetUser(ctx, &user.GetUserParams{ID: order.UserID})
if err != nil {
return nil, err
}
return &OrderWithUser{Order: order, User: orderUser}, nil
}When to Split Services
何时拆分服务
Split when you have:
| Signal | Action |
|---|---|
| Different scaling needs | Split (e.g., auth vs analytics) |
| Different deployment cycles | Split |
| Clear domain boundaries | Split |
| Shared database tables | Keep together |
| Tightly coupled logic | Keep together |
| Just organizing code | Use sub-packages, not services |
出现以下信号时考虑拆分:
| 信号 | 操作 |
|---|---|
| 不同的扩容需求 | 拆分(例如,认证服务 vs 分析服务) |
| 不同的部署周期 | 拆分 |
| 清晰的领域边界 | 拆分 |
| 共享数据库表 | 保持合并 |
| 逻辑高度耦合 | 保持合并 |
| 仅为代码组织 | 使用子包,而非拆分服务 |
Internal Helpers (Non-Service Packages)
内部工具包(非服务包)
Create packages without endpoints for shared code:
//encore:apimy-app/
├── user/
│ └── user.go # Service (has API)
├── order/
│ └── order.go # Service (has API)
└── internal/
├── util/
│ └── util.go # Not a service (no API)
└── validation/
└── validate.go创建不含端点的包用于共享代码:
//encore:apimy-app/
├── user/
│ └── user.go # 服务(包含API)
├── order/
│ └── order.go # 服务(包含API)
└── internal/
├── util/
│ └── util.go # 非服务(无API)
└── validation/
└── validate.goGuidelines
指导原则
- A package becomes a service when it has endpoints
//encore:api - Services cannot be nested within other services
- Start with one service, split when there's a clear reason
- Cross-service calls look like regular function calls
- Each service can have its own database
- Package names should be lowercase, descriptive
- Don't create services just for code organization - use sub-packages instead
- 包含端点的包会成为服务
//encore:api - 服务不能嵌套在其他服务内部
- 从单个服务开始,有明确理由时再拆分
- 跨服务调用看起来与常规函数调用无异
- 每个服务可以拥有独立的数据库
- 包名应使用小写且具有描述性
- 不要仅为了代码组织而创建服务——使用子包替代