encore-go-infrastructure by encoredev/skills
npx skills add https://github.com/encoredev/skills --skill encore-go-infrastructureEncore Go 使用声明式基础设施——您将资源定义为包级变量,Encore 负责配置:
encore run) - Encore 在 Docker 中运行基础设施(Postgres、Redis 等)所有基础设施必须在包级别声明,不能在函数内部。
package user
import "encore.dev/storage/sqldb"
// 正确:包级别
var db = sqldb.NewDatabase("userdb", sqldb.DatabaseConfig{
Migrations: "./migrations",
})
// 错误:函数内部
func setup() {
db := sqldb.NewDatabase("userdb", sqldb.DatabaseConfig{...})
}
在 migrations/ 目录中创建迁移文件:
user/
├── user.go
├── db.go
└── migrations/
├── 1_create_users.up.sql
└── 2_add_email_index.up.sql
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
迁移文件命名格式:{数字}_{描述}.up.sql
package events
import "encore.dev/pubsub"
type OrderCreatedEvent struct {
OrderID string `json:"order_id"`
UserID string `json:"user_id"`
Total int `json:"total"`
}
// 包级别声明
var OrderCreated = pubsub.NewTopic[*OrderCreatedEvent]("order-created", pubsub.TopicConfig{
DeliveryGuarantee: pubsub.AtLeastOnce,
})
msgID, err := events.OrderCreated.Publish(ctx, &events.OrderCreatedEvent{
OrderID: "123",
UserID: "user-456",
Total: 9999,
})
package notifications
import (
"context"
"myapp/events"
"encore.dev/pubsub"
)
var _ = pubsub.NewSubscription(events.OrderCreated, "send-confirmation-email",
pubsub.SubscriptionConfig[*events.OrderCreatedEvent]{
Handler: sendConfirmationEmail,
},
)
func sendConfirmationEmail(ctx context.Context, event *events.OrderCreatedEvent) error {
// 发送邮件...
return nil
}
将主题访问权限传递给库代码,同时保持静态分析:
// 创建具有发布权限的引用
ref := pubsub.TopicRef[pubsub.Publisher[*OrderCreatedEvent]](OrderCreated)
// 在库代码中使用引用
func publishEvent(ref pubsub.Publisher[*OrderCreatedEvent], event *OrderCreatedEvent) error {
_, err := ref.Publish(ctx, event)
return err
}
package cleanup
import (
"context"
"encore.dev/cron"
)
// 定时任务声明
var _ = cron.NewJob("cleanup-sessions", cron.JobConfig{
Title: "清理过期会话",
Schedule: "0 * * * *", // 每小时
Endpoint: CleanupExpiredSessions,
})
//encore:api private
func CleanupExpiredSessions(ctx context.Context) error {
// 清理逻辑
return nil
}
| 格式 | 示例 | 描述 |
|---|---|---|
| Cron 表达式 | "0 9 * * 1" | 每周一上午 9 点 |
| 固定间隔 | "every 1h" | 每小时 |
| 固定间隔 | "every 30m" | 每 30 分钟 |
package uploads
import "encore.dev/storage/objects"
// 包级别
var Uploads = objects.NewBucket("user-uploads", objects.BucketConfig{})
// 公共存储桶
var PublicAssets = objects.NewBucket("public-assets", objects.BucketConfig{
Public: true,
})
// 上传(流式模式)
writer := Uploads.Upload(ctx, "path/to/file.jpg")
_, err := io.Copy(writer, dataReader)
if err != nil {
writer.Abort()
return err
}
err = writer.Close()
// 下载
reader := Uploads.Download(ctx, "path/to/file.jpg")
if err := reader.Err(); err != nil {
return err
}
defer reader.Close()
data, _ := io.ReadAll(reader)
// 检查是否存在
exists, err := Uploads.Exists(ctx, "path/to/file.jpg")
// 获取属性(大小、内容类型、ETag)
attrs, err := Uploads.Attrs(ctx, "path/to/file.jpg")
// 列出对象
for err, entry := range Uploads.List(ctx, &objects.Query{}) {
if err != nil {
return err
}
fmt.Println(entry.Key, entry.Size)
}
// 删除
err := Uploads.Remove(ctx, "path/to/file.jpg")
// 公共 URL(仅适用于公共存储桶)
url := PublicAssets.PublicURL("image.jpg")
生成用于上传/下载的临时 URL,无需暴露您的存储桶:
import "time"
// 签名上传 URL(2 小时后过期)
url, err := Uploads.SignedUploadURL(ctx, "user-uploads/avatar.jpg",
objects.WithTTL(time.Duration(7200)*time.Second))
// 签名下载 URL
url, err := Uploads.SignedDownloadURL(ctx, "documents/report.pdf",
objects.WithTTL(time.Duration(7200)*time.Second))
将具有特定权限的存储桶访问权限传递给库代码:
// 创建仅具有下载权限的引用
ref := objects.BucketRef[objects.Downloader](Uploads)
// 创建具有多个权限的引用
type myPerms interface {
objects.Downloader
objects.Uploader
}
ref := objects.BucketRef[myPerms](Uploads)
// 权限类型:Downloader、Uploader、Lister、Attrser、Remover、
// SignedDownloader、SignedUploader、ReadWriter
package email
var secrets struct {
SendGridAPIKey string
SMTPPassword string
}
func sendEmail() error {
apiKey := secrets.SendGridAPIKey
// 使用密钥...
}
通过 CLI 设置密钥:
encore secret set --type prod SendGridAPIKey
package myservice
import "encore.dev/config"
var cfg struct {
MaxRetries config.Int
BaseURL config.String
Debug config.Bool
}
func doSomething() {
if cfg.Debug() {
log.Println("调试模式已启用")
}
}
private(仅限内部使用)每周安装数
121
仓库
GitHub 星标数
20
首次出现时间
2026 年 1 月 21 日
安全审计
安装于
opencode102
codex101
gemini-cli101
claude-code93
github-copilot83
cursor80
Encore Go uses declarative infrastructure - you define resources as package-level variables and Encore handles provisioning:
encore run) - Encore runs infrastructure in Docker (Postgres, Redis, etc.)All infrastructure must be declared at package level, not inside functions.
package user
import "encore.dev/storage/sqldb"
// CORRECT: Package level
var db = sqldb.NewDatabase("userdb", sqldb.DatabaseConfig{
Migrations: "./migrations",
})
// WRONG: Inside function
func setup() {
db := sqldb.NewDatabase("userdb", sqldb.DatabaseConfig{...})
}
Create migrations in the migrations/ directory:
user/
├── user.go
├── db.go
└── migrations/
├── 1_create_users.up.sql
└── 2_add_email_index.up.sql
Migration naming: {number}_{description}.up.sql
package events
import "encore.dev/pubsub"
type OrderCreatedEvent struct {
OrderID string `json:"order_id"`
UserID string `json:"user_id"`
Total int `json:"total"`
}
// Package level declaration
var OrderCreated = pubsub.NewTopic[*OrderCreatedEvent]("order-created", pubsub.TopicConfig{
DeliveryGuarantee: pubsub.AtLeastOnce,
})
msgID, err := events.OrderCreated.Publish(ctx, &events.OrderCreatedEvent{
OrderID: "123",
UserID: "user-456",
Total: 9999,
})
package notifications
import (
"context"
"myapp/events"
"encore.dev/pubsub"
)
var _ = pubsub.NewSubscription(events.OrderCreated, "send-confirmation-email",
pubsub.SubscriptionConfig[*events.OrderCreatedEvent]{
Handler: sendConfirmationEmail,
},
)
func sendConfirmationEmail(ctx context.Context, event *events.OrderCreatedEvent) error {
// Send email...
return nil
}
Pass topic access to library code while maintaining static analysis:
// Create a reference with publish permission
ref := pubsub.TopicRef[pubsub.Publisher[*OrderCreatedEvent]](OrderCreated)
// Use the reference in library code
func publishEvent(ref pubsub.Publisher[*OrderCreatedEvent], event *OrderCreatedEvent) error {
_, err := ref.Publish(ctx, event)
return err
}
package cleanup
import (
"context"
"encore.dev/cron"
)
// The cron job declaration
var _ = cron.NewJob("cleanup-sessions", cron.JobConfig{
Title: "Clean up expired sessions",
Schedule: "0 * * * *", // Every hour
Endpoint: CleanupExpiredSessions,
})
//encore:api private
func CleanupExpiredSessions(ctx context.Context) error {
// Cleanup logic
return nil
}
| Format | Example | Description |
|---|---|---|
| Cron expression | "0 9 * * 1" | 9am every Monday |
| Every interval | "every 1h" | Every hour |
| Every interval | "every 30m" | Every 30 minutes |
package uploads
import "encore.dev/storage/objects"
// Package level
var Uploads = objects.NewBucket("user-uploads", objects.BucketConfig{})
// Public bucket
var PublicAssets = objects.NewBucket("public-assets", objects.BucketConfig{
Public: true,
})
// Upload (streaming pattern)
writer := Uploads.Upload(ctx, "path/to/file.jpg")
_, err := io.Copy(writer, dataReader)
if err != nil {
writer.Abort()
return err
}
err = writer.Close()
// Download
reader := Uploads.Download(ctx, "path/to/file.jpg")
if err := reader.Err(); err != nil {
return err
}
defer reader.Close()
data, _ := io.ReadAll(reader)
// Check existence
exists, err := Uploads.Exists(ctx, "path/to/file.jpg")
// Get attributes (size, content type, ETag)
attrs, err := Uploads.Attrs(ctx, "path/to/file.jpg")
// List objects
for err, entry := range Uploads.List(ctx, &objects.Query{}) {
if err != nil {
return err
}
fmt.Println(entry.Key, entry.Size)
}
// Delete
err := Uploads.Remove(ctx, "path/to/file.jpg")
// Public URL (only for public buckets)
url := PublicAssets.PublicURL("image.jpg")
Generate temporary URLs for upload/download without exposing your bucket:
import "time"
// Signed upload URL (expires in 2 hours)
url, err := Uploads.SignedUploadURL(ctx, "user-uploads/avatar.jpg",
objects.WithTTL(time.Duration(7200)*time.Second))
// Signed download URL
url, err := Uploads.SignedDownloadURL(ctx, "documents/report.pdf",
objects.WithTTL(time.Duration(7200)*time.Second))
Pass bucket access with specific permissions to library code:
// Create a reference with download permission only
ref := objects.BucketRef[objects.Downloader](Uploads)
// Create a reference with multiple permissions
type myPerms interface {
objects.Downloader
objects.Uploader
}
ref := objects.BucketRef[myPerms](Uploads)
// Permission types: Downloader, Uploader, Lister, Attrser, Remover,
// SignedDownloader, SignedUploader, ReadWriter
package email
var secrets struct {
SendGridAPIKey string
SMTPPassword string
}
func sendEmail() error {
apiKey := secrets.SendGridAPIKey
// Use the secret...
}
Set secrets via CLI:
encore secret set --type prod SendGridAPIKey
package myservice
import "encore.dev/config"
var cfg struct {
MaxRetries config.Int
BaseURL config.String
Debug config.Bool
}
func doSomething() {
if cfg.Debug() {
log.Println("Debug mode enabled")
}
}
private (internal only)Weekly Installs
121
Repository
GitHub Stars
20
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode102
codex101
gemini-cli101
claude-code93
github-copilot83
cursor80
Supabase Postgres 最佳实践指南 - 8大类别性能优化规则与SQL示例
78,800 周安装
Better-Auth 组织管理最佳实践:多租户系统设置、成员权限与邀请系统完整指南
8,200 周安装
Power BI 语义建模最佳实践指南:星型模式、DAX 度量值与模型优化
8,100 周安装
AI 自动生成编码规范 | 基于项目文件智能创建代码风格指南
8,100 周安装
ScoutQA AI驱动Web应用探索性测试工具 - 自动化测试与验证解决方案
8,100 周安装
PlantUML ASCII 图表生成器 - 命令行文本图表工具,支持序列图、类图、活动图
8,200 周安装
pytest-coverage:Python测试覆盖率工具,一键生成代码覆盖率报告
8,300 周安装