Ent schema必须用Go代码定义在ent/schema目录下,不支持YAML或SQL;id默认int、外键须带_id后缀、时间字段用Time类型并注解SQLType;生成需在项目根目录执行ent generate ./ent/schema;约束通过函数链式调用实现,如index.Fields("email").Unique()。

Ent schema定义必须用Go代码写,不是YAML或SQL
Ent不接受外部DSL,所有表结构、字段、关系都得在ent/schema目录下的Go文件里用结构体和方法描述。这是它和GORM、SQLBoiler最根本的区别——没有“迁移文件”概念,只有“schema源码”。
常见错误是试图把MySQL建表语句直接转成Ent schema,结果漏掉Edges或Mixins导致生成失败;或者给Field加了sql.NullString这类类型,但Ent只认原生Go类型(如string)。
-
id字段默认存在且为int,若要用uuid,必须显式调用IDType并配Default+SchemaType - 外键字段名必须带
_id后缀(如user_id),否则Edge无法自动关联 - 时间字段推荐用
Time类型,并加Annotations指定数据库类型:schema.TimeType{SQLType: "datetime"}
entgine生成命令要进项目根目录再跑
很多人在ent/schema目录下执行ent generate ./schema,结果报错no Go files in ...——因为entc需要读取整个模块的go.mod和包路径,必须在项目根目录运行。
正确命令是:ent generate ./ent/schema(注意路径是相对于当前目录的,且./ent/schema需存在)。如果ent目录不在根下,比如在internal/ent,那路径就得写全。
立即学习“go语言免费学习笔记(深入)”;
- 首次生成前确保已运行
go mod init并安装entgo.io/ent/cmd/ent - 生成后会覆盖
ent/client.go和ent/schema/*.go,别手动改这些文件 - 想看生成了啥,加
--verbose参数,能输出每张表对应的ent.User结构体字段
字段约束得靠SchemaConfig和StorageKey控制
Ent不提供类似NOT NULL或UNIQUE的字符串声明,所有约束都通过函数链式调用实现。比如Unique()不是加在字段上,而是调用Index时组合使用。
容易被忽略的是StorageKey:它决定数据库列名。如果不设,默认用字段名小写(CreatedAt → created_at),但如果你的旧表用create_time,就必须显式写StorageKey("create_time"),否则查询会找不到列。
-
Optional()对应NULL,Nillable()才允许Go层传nil指针 - 唯一索引要这样写:
index.Fields("email").Unique(),不能只写Unique() - 软删除字段必须叫
deleted_at,且类型为time.Time,Ent才识别为SoftDelete行为
查询时Where条件拼接容易漏and/or分组
Ent的Where不支持直接写AND email LIKE ? AND status = ?,所有条件必须用and或or包装,否则生成的SQL会出错。
比如查“邮箱包含‘gmail’且状态为激活”,得写client.User.Query().Where(and(ContainsEmail("gmail"), EqStatus(1)))。如果漏掉and,Ent会当成两个独立WHERE子句,数据库报语法错。
- 预定义谓词(如
ContainsEmail)要先用client.User.Where注册,不能直接用字符串 - 模糊查询用
Contains,不是Like;大小写敏感由数据库collation决定,Ent不干预 - 分页必须用
Offset/Limit,Page是辅助函数,底层还是转成Offset
ent generate,而且生成逻辑依赖整个模块的类型系统——所以别把ent目录挪到vendor里,也别用replace指向本地ent fork,否则生成器可能找不到依赖的接口定义。


















