轻量级、高性能的 Go MySQL 数据访问库。
daog 不是传统的 ORM 框架,而是通过编译时代码生成实现高性能数据访问,避免运行时反射开销。
- 零反射: 通过 compilex 工具编译生成代码,性能与原生 SQL 操作相当
- 泛型支持: 使用 Go 泛型提供编译时类型检查
- 分库分表: 内置数据源分片和表分片支持
- 链式 API: 灵活的条件构建器(Matcher)防止 SQL 注入
- 事务管理: 简洁的事务上下文管理
go get github.com/rolandhe/daog安装代码生成工具:
go install github.com/rolandhe/compilex@latestCREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL,
`age` int NOT NULL DEFAULT 0,
`created_at` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;compilex -i="user.sql" -pkg dal -o ./dal生成两个文件:
User.go: 数据结构、元数据、QuickDao(不可修改)User-ext.go: 扩展文件,可添加自定义逻辑
package main
import (
"github.com/rolandhe/daog"
_ "github.com/go-sql-driver/mysql"
)
func main() {
conf := &daog.DbConf{
DbUrl: "user:password@tcp(localhost:3306)/dbname?parseTime=true",
Size: 10,
Life: 3600,
IdleCons: 5,
IdleTime: 600,
LogSQL: true,
}
ds, err := daog.NewDatasource(conf)
if err != nil {
panic(err)
}
defer ds.Shutdown()
}import (
"time"
"github.com/rolandhe/daog"
"github.com/rolandhe/daog/ttypes"
txrequest "github.com/rolandhe/daog/tx"
"your/project/dal"
)
// 插入
func createUser(ds daog.Datasource) error {
return daog.AutoTrans(func() (*daog.TransContext, error) {
return daog.NewTransContext(ds, txrequest.RequestWrite, "trace-id")
}, func(tc *daog.TransContext) error {
user := &dal.User{
Name: "张三",
Age: 25,
CreatedAt: ttypes.NormalDatetime(time.Now()),
}
_, err := dal.UserDao.Insert(tc, user)
// user.Id 已自动回填
return err
})
}
// 查询
func getUser(ds daog.Datasource, id int64) (*dal.User, error) {
return daog.AutoTransWithResult(func() (*daog.TransContext, error) {
return daog.NewTransContext(ds, txrequest.RequestReadonly, "trace-id")
}, func(tc *daog.TransContext) (*dal.User, error) {
return dal.UserDao.GetById(tc, id)
})
}
// 条件查询
func queryUsers(ds daog.Datasource) ([]*dal.User, error) {
return daog.AutoTransWithResult(func() (*daog.TransContext, error) {
return daog.NewTransContext(ds, txrequest.RequestReadonly, "trace-id")
}, func(tc *daog.TransContext) ([]*dal.User, error) {
matcher := daog.NewMatcher().Gt(dal.UserFields.Age, 18)
return dal.UserDao.QueryListMatcher(tc, matcher)
})
}
// 更新
func updateUser(ds daog.Datasource, id int64, newAge int) error {
return daog.AutoTrans(func() (*daog.TransContext, error) {
return daog.NewTransContext(ds, txrequest.RequestWrite, "trace-id")
}, func(tc *daog.TransContext) error {
modifier := daog.NewModifier().Add(dal.UserFields.Age, newAge)
_, err := dal.UserDao.UpdateById(tc, modifier, id)
return err
})
}
// 删除
func deleteUser(ds daog.Datasource, id int64) error {
return daog.AutoTrans(func() (*daog.TransContext, error) {
return daog.NewTransContext(ds, txrequest.RequestWrite, "trace-id")
}, func(tc *daog.TransContext) error {
_, err := dal.UserDao.DeleteById(tc, id)
return err
})
}- 架构设计 - 设计原理与核心组件
- 快速入门 - 环境准备与第一个示例
- CRUD 操作 - 增删改查详解
- 条件构建器 - Matcher 使用指南
- 事务管理 - TransContext 与事务处理
- 分库分表 - 数据源与表分片
- 自定义类型 - ttypes 包类型说明
- 代码生成 - compilex 工具使用
数据源用于描述一个 MySQL database 的连接池:
conf := &daog.DbConf{
DbUrl: "user:pass@tcp(host:3306)/db?parseTime=true",
Size: 10, // 最大连接数
Life: 3600, // 连接最大生命周期(秒)
IdleCons: 5, // 最大空闲连接数
IdleTime: 600, // 最大空闲时间(秒)
LogSQL: true, // 是否记录 SQL
GetConnTimeout: 10, // 获取连接超时(秒)
}
ds, err := daog.NewDatasource(conf)事务上下文是所有数据库操作的执行环境,支持三种事务类型:
| 类型 | 常量 | 说明 |
|---|---|---|
| 无事务 | txrequest.RequestNone |
每条 SQL 独立执行 |
| 只读事务 | txrequest.RequestReadonly |
只读操作,性能更优 |
| 读写事务 | txrequest.RequestWrite |
支持所有操作 |
由 compilex 工具自动生成,描述表结构与 Go struct 的映射关系。
用于安全构建 WHERE 子句,防止 SQL 注入:
matcher := daog.NewMatcher().
Eq("status", 1).
Gt("age", 18).
Like("name", "张", daog.LikeStyleRight)每张表生成的便捷接口,无需传递 TableMeta 参数:
// 使用函数方式
user, err := daog.GetById(tc, id, dal.UserMeta)
// 使用 QuickDao 方式
user, err := dal.UserDao.GetById(tc, id)daog 的核心思想是编译优于反射:
- 通过 compilex 工具将 CREATE TABLE 语句编译为 Go 代码
- 生成的代码包含表元数据和字段映射函数,无需运行时反射
- 利用 Go 泛型提供类型安全,避免 interface{} 类型断言
这种方式的优势:
- 性能与手写 SQL 代码相当
- 编译时发现类型错误
- IDE 友好,支持代码补全
MIT License