简体中文 | English
go-sail是一个轻量的渐进式Web框架,使用Go语言实现。它并不是重复造轮子的产物,而是站在巨人的肩膀上,整合现有的优秀组件,旨在帮助使用者以最简单的方式构建稳定可靠的服务。
正如它的名字一般,你可以把它视作自己在golang生态的一个开始。go-sail将助力你从轻出发,扬帆起航。
推荐go version >= 1.20
go get -u github.com/keepchen/go-sail/v3
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/keepchen/go-sail/v3/sail"
"github.com/keepchen/go-sail/v3/sail/config"
)
var (
conf = &config.Config{}
registerRoutes = func(ginEngine *gin.Engine) {
ginEngine.GET("/hello", func(c *gin.Context){
c.String(http.StatusOK, "%s", "hello, world!")
})
}
)
func main() {
sail.WakeupHttp("go-sail", conf).Hook(registerRoutes, nil, nil).Launch()
}
当你看到终端如下图所示内容就表示服务启动成功了:
parseFn := func(content []byte, viaWatch bool){
fmt.Println("config content: ", string(content))
if viaWatch {
//reload config...
}
}
etcdConf := etcd.Conf{
endpoints: "",
username: "",
password: "",
}
key := "go-sail.config.yaml"
sail.Config(true, parseFn).ViaEtcd(etcdConf, key).Parse(parseFn)
func UserRegisterSvc(c *gin.Context) {
...
sail.LogTrace(c).GetLogger().Warn("log something...")
...
}
- 颁发令牌
func UserLoginSvc(c *gin.Context) {
...
uid := "user-1000"
exp := time.Now().Add(time.Hour * 24).Unix()
otherFields := map[string]interface{}{
"nickname": "go-sail",
"avatar": "https://go-sail.dev/assets/avatar/1.png",
...
}
ok, claims, err := sail.JWT().MakeToken(uid, exp, otherFields)
...
}
- 认证
func UserInfoSvc(c *gin.Context) {
...
ok, claims, err := sail.JWT().ValidToken(token)
...
}
func UserInfoSvc(c *gin.Context) {
sail.Response(c).Wrap(constants.ErrNone, resp).Send()
}
- 读写分离
func UserInfoSvc(c *gin.Context) {
uid := "user-1000"
var user models.User
//READ: query user info
sail.GetDBR().Where("uid = ?", uid).First(&user)
...
//WRITE: update user info
sail.GetDBW().Model(&models.User{}).
Where("uid = ?", uid).
Updates(map[string]interface{}{
"avatar": "https://go-sail.dev/assets/avatar/2.png"
})
}
- 事务
func UserInfoSvc(c *gin.Context) {
uid := "user-1000"
err := sail.GetDBW().Transaction(func(tx *gorm.DB){
e1 := tx.Model(&models.User{}).
Where("uid = ?", uid).
Updates(map[string]interface{}{
"avatar": "https://go-sail.dev/assets/avatar/2.png"
}).Error
if e1 != nil {
return e1
}
e2 := tx.Create(&models.UserLoginHistory{
Uid: uid,
...
}).Error
return e2
})
}
func UserInfoSvc(c *gin.Context) {
...
sail.GetRedis().Set(ctx, "go-sail:userInfo", "user-1000", time.Hour*24).Result()
...
}
- 周期性的
func TodoSomething() {
fn := func() { ... }
sail.Schedule("todoSomething", fn).Daily()
}
- Linux Crontab风格的
func TodoSomething() {
fn := func() { ... }
sail.Schedule("todoSomething", fn).RunAt("*/5 * * * *")
}
- 竞态检测
func TodoSomething() {
fn := func() { ... }
sail.Schedule("todoSomething", fn).Withoutoverlapping().RunAt("*/5 * * * *")
}
func UpdateUserBalance() {
if !sail.RedisLocker().TryLock(key) {
return false
}
defer sail.RedisLocker().Unlock(key)
...
}
- HTTP响应器
- 统一响应字段
- 管理HTTP状态码
- 管理业务码
- 组件库
- Database
- Jwt
- Kafka
- Logger
- Nacos
- Etcd
- Nats
- Redis
- Valkey
- 服务注册与发现
- Nacos
- Etcd
- 工具类
- 加解密
- 文件
- ip
- 字符串
- 随机数
- 日期时间
- ...
- 日志收集与导出
- 本地文件
- 导出器
- Redis
- Kafka
- Nats
- 计划任务
- 可取消的
- 一次性的
- 周期性的
- Linux Crontab风格的
- 竞态检测
- 遥测与可观测性
- 调用链追踪
- Prometheus
- Pprof
- 日志导出器
- 性能检测
- Prometheus
- Pprof
- 接口错误码
- 动态注入
- 国际化
- 基于Redis的分布式锁
- 阻塞式
- 非阻塞式
- 接口文档
- Redocly
- Swagger
- 配置管理
- File
- Etcd
- Nacos
感谢在体验、使用过程中提出宝贵建议和意见以及提供过其他各种帮助的各位小伙伴!
- 配置模块化优化建议 @fujilin
- 响应器语法糖增强优化建议 @lichuanzhang
- Logo美化 @ShuaiRen34
- 欢迎大家提PR: pull request
- 欢迎大家提出自己的想法: issue
- 感谢你的star如果你喜欢这个项目的话 :)
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |