Structure de Service Encore Go
Instructions
Dans Encore Go, chaque package avec un endpoint API est automatiquement un service. Aucune configuration spéciale nécessaire.
Créer un Service
Créez simplement un package avec au moins un endpoint //encore:api :
// 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) {
// Cela fait de "user" un service
}
Structure Minimale de Service
user/
├── user.go # API endpoints
├── db.go # Base de données (si nécessaire)
└── migrations/ # Migrations SQL
└── 1_create_users.up.sql
Modèles d'Application
Service Unique (Recommandé au Démarrage)
Idéal pour les nouveaux projets - commencez simplement, divisez si nécessaire :
my-app/
├── encore.app
├── go.mod
├── api.go # Tous les endpoints
├── db.go # Base de données
└── migrations/
└── 1_initial.up.sql
Multi-Service
Pour les systèmes distribués avec des limites de domaine claires :
my-app/
├── encore.app
├── go.mod
├── user/
│ ├── user.go
│ ├── db.go
│ └── migrations/
├── order/
│ ├── order.go
│ ├── db.go
│ └── migrations/
└── notification/
└── notification.go
Application Large (Basée sur Systèmes)
Groupez les services connexes dans des systèmes :
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
Appels Service-to-Service
Importez et appelez la fonction directement - Encore gère le RPC :
package order
import (
"context"
"myapp/user" // Importer le service 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
}
// Cela devient un appel RPC - Encore le gère
orderUser, err := user.GetUser(ctx, &user.GetUserParams{ID: order.UserID})
if err != nil {
return nil, err
}
return &OrderWithUser{Order: order, User: orderUser}, nil
}
Quand Diviser les Services
Divisez quand vous avez :
| Signal | Action |
|---|---|
| Besoins de scaling différents | Diviser (ex. authentification vs analytics) |
| Cycles de déploiement différents | Diviser |
| Limites de domaine claires | Diviser |
| Tables de base de données partagées | Garder ensemble |
| Logique étroitement couplée | Garder ensemble |
| Juste organiser le code | Utiliser des sous-packages, pas des services |
Helpers Internes (Packages Non-Service)
Créez des packages sans endpoints //encore:api pour le code partagé :
my-app/
├── user/
│ └── user.go # Service (a une API)
├── order/
│ └── order.go # Service (a une API)
└── internal/
├── util/
│ └── util.go # Pas un service (pas d'API)
└── validation/
└── validate.go
Recommandations
- Un package devient un service quand il a des endpoints
//encore:api - Les services ne peuvent pas être imbriqués dans d'autres services
- Commencez avec un service, divisez quand il y a une raison claire
- Les appels cross-service ressemblent à des appels de fonction ordinaires
- Chaque service peut avoir sa propre base de données
- Les noms de packages doivent être en minuscules, descriptifs
- Ne créez pas de services juste pour organiser le code - utilisez des sous-packages à la place