| name | encore-go-code-review |
| description | Review Encore Go code for best practices. |
Encore Go Code Review
Instructions
When reviewing Encore Go code, check for these common issues:
Critical Issues
1. Infrastructure Inside Functions
func setup() {
db := sqldb.NewDatabase("mydb", sqldb.DatabaseConfig{...})
topic := pubsub.NewTopic[*Event]("events", pubsub.TopicConfig{...})
}
var db = sqldb.NewDatabase("mydb", sqldb.DatabaseConfig{
Migrations: "./migrations",
})
var topic = pubsub.NewTopic[*Event]("events", pubsub.TopicConfig{
DeliveryGuarantee: pubsub.AtLeastOnce,
})
2. Missing Context Parameter
func GetUser(params *GetUserParams) (*User, error) {
}
func GetUser(ctx context.Context, params *GetUserParams) (*User, error) {
}
3. SQL Injection Risk
query := fmt.Sprintf("SELECT * FROM users WHERE email = '%s'", email)
rows, err := db.Query(ctx, query)
rows, err := sqldb.Query[User](ctx, db, `
SELECT * FROM users WHERE email = $1
`, email)
4. Wrong Return Types
func GetUser(ctx context.Context, params *GetUserParams) (User, error) {
}
func GetUser(ctx context.Context, params *GetUserParams) (*User, error) {
}
5. Ignoring Errors
user, _ := sqldb.QueryRow[User](ctx, db, query, id)
user, err := sqldb.QueryRow[User](ctx, db, query, id)
if err != nil {
return nil, err
}
Warning Issues
6. Not Checking for ErrNoRows
func getUser(ctx context.Context, id string) (*User, error) {
user, err := sqldb.QueryRow[User](ctx, db, `
SELECT * FROM users WHERE id = $1
`, id)
if err != nil {
return nil, err
}
return user, nil
}
import "errors"
func getUser(ctx context.Context, id string) (*User, error) {
user, err := sqldb.QueryRow[User](ctx, db, `
SELECT * FROM users WHERE id = $1
`, id)
if errors.Is(err, sqldb.ErrNoRows) {
return nil, &errs.Error{
Code: errs.NotFound,
Message: "user not found",
}
}
if err != nil {
return nil, err
}
return user, nil
}
7. Public Internal Endpoints
func CleanupJob(ctx context.Context) error {
}
func CleanupJob(ctx context.Context) error {
}
8. Non-Idempotent Subscription Handlers
var _ = pubsub.NewSubscription(OrderCreated, "process-order",
pubsub.SubscriptionConfig[*OrderCreatedEvent]{
Handler: func(ctx context.Context, event *OrderCreatedEvent) error {
return chargeCustomer(ctx, event.OrderID)
},
},
)
var _ = pubsub.NewSubscription(OrderCreated, "process-order",
pubsub.SubscriptionConfig[*OrderCreatedEvent]{
Handler: func(ctx context.Context, event *OrderCreatedEvent) error {
order, err := getOrder(ctx, event.OrderID)
if err != nil {
return err
}
if order.Status != "pending" {
return nil
}
return chargeCustomer(ctx, event.OrderID)
},
},
)
9. Not Closing Query Rows
func listUsers(ctx context.Context) ([]*User, error) {
rows, err := sqldb.Query[User](ctx, db, `SELECT * FROM users`)
if err != nil {
return nil, err
}
var users []*User
for rows.Next() {
users = append(users, rows.Value())
}
return users, nil
}
func listUsers(ctx context.Context) ([]*User, error) {
rows, err := sqldb.Query[User](ctx, db, `SELECT * FROM users`)
if err != nil {
return nil, err
}
defer rows.Close()
var users []*User
for rows.Next() {
users = append(users, rows.Value())
}
return users, rows.Err()
}
Review Checklist
Output Format
When reviewing, report issues as:
[CRITICAL] [file:line] Description of issue
[WARNING] [file:line] Description of concern
[GOOD] Notable good practice observed