Go 应用骨架 SDK,可作为项目的 core 模块快速搭建服务。
| 模块 | 说明 |
|---|---|
| config | 基于 viper,支持本地文件 / etcd / consul 远程配置,支持配置热更新,支持 a.b.c 格式获取自定义配置 |
| logger | 基于 zap + lumberjack,支持 JSON / console 格式,日志轮转 |
| database | 基于 gorm,支持 MySQL / PostgreSQL / SQLite,多实例按名称获取,可配置日志级别 |
| redis | 基于 go-redis/v9,多实例按名称获取 |
| lock | 基于 Redis 的分布式锁,支持重试、续期,使用 crypto/rand 保证唯一性 |
| elasticsearch | 基于 go-elasticsearch/v8,多实例按名称获取 |
| meilisearch | 基于 meilisearch-go,多实例按名称获取 |
| kafka | 基于 segmentio/kafka-go,支持生产 / 消费 |
| rabbitmq | 基于 amqp091-go,支持发布 / 消费 / 声明队列和交换机 |
| storage/oss | 阿里云 OSS 存储 |
| storage/cos | 腾讯云 COS 存储 |
| cron | 基于 robfig/cron/v3,支持秒级精度 |
| idgen | 基于 yitter/idgenerator-go,支持本地 / Redis 分布式 ID 生成 |
| server/http | 基于 gin,内置 zap 日志和 panic recovery 中间件 |
| server/grpc | 基于 grpc-go,内置日志和 recovery 拦截器(使用原生 ChainInterceptor) |
| response | 统一 HTTP / gRPC 响应格式 |
| middleware | CORS、RequestID、JWT 认证中间件 |
go get github.com/attains/go-skeleton-
复制
config.example.yaml为config.yaml并修改配置。 -
编写代码:
package main
import (
"log"
sk "github.com/attains/go-skeleton"
"github.com/attains/go-skeleton/config"
"github.com/attains/go-skeleton/middleware"
"github.com/attains/go-skeleton/response"
"github.com/gin-gonic/gin"
)
func main() {
app, err := sk.New(
sk.WithConfig(config.WithFile("config.yaml")),
sk.WithDB(),
sk.WithRedis(),
sk.WithHTTP(),
sk.WithGRPC(),
sk.WithCron(),
sk.WithIDGen(),
)
if err != nil {
log.Fatal(err)
}
// 注册中间件
app.HTTPServer.Engine().Use(middleware.CORS())
app.HTTPServer.Engine().Use(middleware.RequestID())
// 注册 HTTP 路由
app.HTTPServer.Engine().GET("/ping", func(c *gin.Context) {
response.OK(c, gin.H{"message": "pong"})
})
// 需要认证的路由
auth := app.HTTPServer.Engine().Group("/api", middleware.JWTAuth([]byte("your-secret")))
auth.GET("/profile", func(c *gin.Context) {
userID := middleware.GetUserID(c)
response.OK(c, gin.H{"user_id": userID})
})
// 注册 gRPC 服务
// pb.RegisterXxxServer(app.GRPCServer.Server(), &service{})
// 添加定时任务
app.Cron.AddFunc("0 */5 * * * *", func() {
// 每5分钟执行
})
// 启动服务(同时启动 HTTP + gRPC + Cron,阻塞等待退出信号)
if err := app.Run(); err != nil {
log.Fatal(err)
}
}通过 With*() 选项按需启用模块,未启用的模块不会初始化连接:
// 只启用 HTTP + 数据库
app, _ := sk.New(
sk.WithConfig(config.WithFile("config.yaml")),
sk.WithDB(),
sk.WithHTTP(),
)
// 启用全部模块
app, _ := sk.New(
sk.WithConfig(config.WithFile("config.yaml")),
sk.WithAll(),
)数据库、Redis、Elasticsearch、Meilisearch 均支持多实例,通过名称获取:
// 获取默认实例(name=default)
db, err := app.DB.Get()
rdb, err := app.Redis.Get()
// 获取指定名称实例
db, err := app.DB.Get("secondary")
rdb, err := app.Redis.Get("cache")
// panic 版本(适合初始化阶段)
db := app.DB.MustGet()import "github.com/attains/go-skeleton/lock"
// 使用默认 Redis 实例获取锁
l, err := app.AcquireLock(ctx, "order:123",
lock.WithTTL(10*time.Second),
lock.WithRetry(3, 200*time.Millisecond),
)
if err != nil {
// 获取锁失败
}
defer l.Release(ctx)
// 指定 Redis 实例
l, err := app.AcquireLockOn(ctx, "cache", "order:123")import "github.com/attains/go-skeleton/idgen"
id := idgen.NextID()import "github.com/attains/go-skeleton/response"
// HTTP 响应
response.OK(c, data) // {"code":0,"message":"ok","data":...}
response.OKWithPage(c, list, total, page, size) // 分页响应
response.Fail(c, 10001, "业务错误") // {"code":10001,"message":"业务错误"}
response.BadRequest(c, "参数错误")
response.Unauthorized(c, "未登录")
response.ServerError(c, "内部错误")
// gRPC 错误
return nil, response.GRPCInvalidArgument("参数错误")
return nil, response.GRPCNotFound("资源不存在")import "github.com/attains/go-skeleton/middleware"
// CORS
engine.Use(middleware.CORS())
engine.Use(middleware.CORS(middleware.CORSConfig{
AllowOrigins: []string{"https://example.com"},
}))
// RequestID — 自动生成或透传 X-Request-ID
engine.Use(middleware.RequestID())
// JWT 认证
engine.Use(middleware.JWTAuth([]byte("signing-key")))
// 生成 Token
token, _ := middleware.GenerateToken(middleware.JWTConfig{
SigningKey: []byte("signing-key"),
Issuer: "my-app",
ExpireIn: 24 * time.Hour,
}, userID, username)
// 在 handler 中获取用户信息
userID := middleware.GetUserID(c)
username := middleware.GetUsername(c)app, _ := sk.New(
sk.WithConfig(
config.WithFile("config.yaml"),
config.WithWatch(func() {
// 配置变更回调
log.Println("config changed")
}),
),
)app, _ := sk.New(
sk.WithConfig(
config.WithRemote("etcd3", "http://127.0.0.1:2379", "/config/myapp", "yaml"),
config.WithWatch(nil),
),
)配置文件中未在结构体中定义的字段,可通过 a.b.c 格式获取:
val := app.Config.GetString("custom.feature_flag")
num := app.Config.GetInt("custom.max_retry")
ok := app.Config.GetBool("custom.enabled")go-skeleton/
├── skeleton.go # 核心 App 引导,组装所有模块
├── config/ # 配置解析(viper)
├── logger/ # 日志(zap)
├── database/ # 数据库(gorm)
├── redis/ # Redis
├── lock/ # 分布式锁
├── elasticsearch/ # Elasticsearch
├── meilisearch/ # Meilisearch
├── kafka/ # Kafka
├── rabbitmq/ # RabbitMQ
├── storage/
│ ├── oss/ # 阿里云 OSS
│ └── cos/ # 腾讯云 COS
├── cron/ # 定时任务
├── idgen/ # 分布式 ID 生成
├── response/ # 统一响应格式
├── middleware/ # HTTP 中间件(CORS / RequestID / JWT)
└── server/
├── http/ # HTTP 服务(gin)
└── grpc/ # gRPC 服务