Skip to content

rolandhe/daog

Repository files navigation

daog

轻量级、高性能的 Go MySQL 数据访问库。

daog 不是传统的 ORM 框架,而是通过编译时代码生成实现高性能数据访问,避免运行时反射开销。

特性

  • 零反射: 通过 compilex 工具编译生成代码,性能与原生 SQL 操作相当
  • 泛型支持: 使用 Go 泛型提供编译时类型检查
  • 分库分表: 内置数据源分片和表分片支持
  • 链式 API: 灵活的条件构建器(Matcher)防止 SQL 注入
  • 事务管理: 简洁的事务上下文管理

安装

go get github.com/rolandhe/daog

安装代码生成工具:

go install github.com/rolandhe/compilex@latest

快速开始

1. 准备表结构

CREATE 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;

2. 生成代码

compilex -i="user.sql" -pkg dal -o ./dal

生成两个文件:

  • User.go: 数据结构、元数据、QuickDao(不可修改)
  • User-ext.go: 扩展文件,可添加自定义逻辑

3. 配置数据源

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()
}

4. 执行 CRUD 操作

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
    })
}

文档

核心概念

Datasource(数据源)

数据源用于描述一个 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)

TransContext(事务上下文)

事务上下文是所有数据库操作的执行环境,支持三种事务类型:

类型 常量 说明
无事务 txrequest.RequestNone 每条 SQL 独立执行
只读事务 txrequest.RequestReadonly 只读操作,性能更优
读写事务 txrequest.RequestWrite 支持所有操作

TableMeta(表元数据)

由 compilex 工具自动生成,描述表结构与 Go struct 的映射关系。

Matcher(条件构建器)

用于安全构建 WHERE 子句,防止 SQL 注入:

matcher := daog.NewMatcher().
    Eq("status", 1).
    Gt("age", 18).
    Like("name", "张", daog.LikeStyleRight)

QuickDao

每张表生成的便捷接口,无需传递 TableMeta 参数:

// 使用函数方式
user, err := daog.GetById(tc, id, dal.UserMeta)

// 使用 QuickDao 方式
user, err := dal.UserDao.GetById(tc, id)

设计理念

daog 的核心思想是编译优于反射

  1. 通过 compilex 工具将 CREATE TABLE 语句编译为 Go 代码
  2. 生成的代码包含表元数据和字段映射函数,无需运行时反射
  3. 利用 Go 泛型提供类型安全,避免 interface{} 类型断言

这种方式的优势:

  • 性能与手写 SQL 代码相当
  • 编译时发现类型错误
  • IDE 友好,支持代码补全

许可证

MIT License

About

轻量级的、高效的、纯golang的mysql访问组件

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages