加入一个拥有庞大代码库的现有项目可能是一项艰巨的任务。
理解应用程序的数据模型对于开发者开始以往项目的工作至关重要。解决这一挑战并帮助开发者把握应用程序数据模型的常用工具之一是 ER(实体关系)图。
ER 图提供了你数据模型的可视化表示,细述了实体的每一个字段。许多工具可以帮助创建这些图,其中一个例子是 Jetbrains DataGrip, 它可以通过连接并检查现有数据库来生成 ER 图:

DataGrip ER 图示例
Ent,一款简单而强大的 Go 语言实体框架,最初是在 Facebook 内部开发,用来处理大型和复杂数据模型的项目。因此 Ent 使用代码生成——它提供类型安全和代码补全,帮助阐释数据模型并提高开发效率。再加上,自动生成保持高层视图的 ER 图并以视觉上令人愉悦的方式展示数据模型不是更好吗?(我的意思是,谁不爱可视化?)
引入 entviz
entviz 是一个 Ent 扩展,能够自动生成静态 HTML 页面来可视化你的数据图。

Entviz 示例输出
如果你想了解 entviz 是如何实现的,查看 实现章节。
查看实际效果
首先,让我们把 entviz 扩展添加到我们的 entc.go 文件中:
go get github.com/hedwigz/entviz
如果你不熟悉 entc,欢迎阅读 entc 文档 进一步了解。
import (
"log"
"entgo.io/ent/entc"
"entgo.io/ent/entc/gen"
"github.com/hedwigz/entviz"
)
func main() {
err := entc.Generate("./schema", &gen.Config{}, entc.Extensions(entviz.Extension{}))
if err != nil {
log.Fatalf("running ent codegen: %v", err)
}
}
假设我们有一个简单的模式,其中包括一个用户实体和一些字段:
// Fields of the User.
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("name"),
field.String("email"),
field.Time("created").
Default(time.Now),
}
}
现在,entviz 将在每次运行时自动生成图形的可视化:
go generate ./...
你现在应该能在你的 Ent 目录中看到一个名为 schema-viz.html 的新文件:
$ ll ./ent/schema-viz.html
-rw-r--r-- 1 hedwigz hedwigz 7.3K Aug 27 09:00 schema-viz.html
在你喜欢的浏览器中打开 html 文件查看可视化效果

接下来,我们再添加一个名为 Post 的实体,并观察可视化的变化:
ent new Post
// Fields of the Post.
func (Post) Fields() []ent.Field {
return []ent.Field{
field.String("content"),
field.Time("created").
Default(time.Now),
}
}
现在,我们在 User 到 Post 之间添加一个(O2M)边:
// Edges of the User.
func (User) Edges() []ent.Edge {
return []ent.Edge{
edge.To("posts", Post.Type),
}
}
最后重新生成代码:
go generate ./...
刷新你的浏览器查看更新的结果!

实现
Entviz 通过扩展 Ent 的 扩展 API 实现。Ent 的扩展 API 允许你聚合多个 模板、钩子、选项 和 注解。例如,entviz 使用模板添加另一个 Go 文件 entviz.go,它公开了 ServeEntviz 方法,可以作为 http 处理器使用,如下所示:
func main() {
http.ListenAndServe("localhost:3002", ent.ServeEntviz())
}
我们定义了一个嵌入默认扩展的扩展结构体,并通过 Templates 方法导出我们的模板:
//go:embed entviz.go.tmpl
var tmplfile string
type Extension struct {
entc.DefaultExtension
}
func (Extension) Templates() []*gen.Template {
return []*gen.Template{
gen.MustParse(gen.NewTemplate("entviz").Parse(tmplfile)),
}
}
模板文件是我们想生成的代码:
{{ define "entviz"}}
{{ $pkg := base $.Config.Package }}
{{ template "header" $ }}
import (
_ "embed"
"net/http"
"strings"
"time"
)
//go:embed schema-viz.html
var html string
func ServeEntviz() http.Handler {
generateTime := time.Now()
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
http.ServeContent(w, req, "schema-viz.html", generateTime, strings.NewReader(html))
})
}
{{ end }}
就这样!现在我们在 ent 包中拥有了一个新方法。
总结
我们看到 ER 图如何帮助开发者跟踪他们的数据模型。随后,我们介绍了 entviz,一个自动为 Ent 模式生成 ER 图的扩展。我们了解了 entviz 如何利用 Ent 的扩展 API 对代码生成进行扩展并添加额外功能。最后,你亲眼看到了通过在自己的项目中安装和使用 entviz 的实际效果。如果你喜欢这段代码,或者想贡献代码——欢迎查看 GitHub 项目。
有问题吗?需要帮助入门?随时加入我们的 Discord 服务器 或者 Slack 频道。
- 订阅我们的 新闻简报
- 关注我们的 Twitter
- 加入 Gophers Slack 的 #ent 频道
- 加入我们的 Ent Discord 服务器