使用Facebook/Ent构建简单CMS系统的Go入门指南

使用Facebook/Ent构建简单CMS系统的Go入门指南

ent ent 项目地址: https://gitcode.com/gh_mirrors/ent4/ent

前言

在当今的Web开发领域,Go语言因其简洁性和高性能而广受欢迎。然而,对于许多Go初学者来说,如何有效地处理数据库操作仍然是一个挑战。Facebook开源的Ent框架正是为解决这一问题而生,它提供了一种类型安全、高效的方式来处理Go应用程序中的数据持久化。

Ent框架简介

Ent是一个用于Go的实体框架,与传统ORM相比具有几个显著特点:

  1. 类型安全的Go API:完全避免使用interface{}和反射,提供纯Go代码实现,编辑器能理解,编译器能检查
  2. 图形语义数据建模:使用图形语义来建模应用数据,便于遍历复杂数据集
  3. 自动生成服务器代码:可生成GraphQL、gRPC或OpenAPI兼容的API层代码
  4. 内置Atlas集成:强大的模式管理工具,支持自动规划模式迁移

环境准备

在开始之前,请确保已安装:

  • Go 1.16+
  • Docker(用于运行MySQL数据库)

第一步:建立数据库模式

初始化项目

首先创建一个新的Go模块:

go mod init example.com/simple-cms

安装Ent框架:

go get -u entgo.io/ent@master

创建数据模型

使用Ent CLI初始化User和Post实体:

go run -mod=mod entgo.io/ent/cmd/ent new User Post

这会创建基本的项目结构:

ent/
├── generate.go
└── schema/
    ├── post.go
    └── user.go

定义模式

user.go中定义User实体:

func (User) Fields() []ent.Field {
    return []ent.Field{
        field.String("name"),
        field.String("email").Unique(),
        field.Time("created_at").Default(time.Now),
    }
}

func (User) Edges() []ent.Edge {
    return []ent.Edge{
        edge.To("posts", Post.Type),
    }
}

post.go中定义Post实体:

func (Post) Fields() []ent.Field {
    return []ent.Field{
        field.String("title"),
        field.Text("body"),
        field.Time("created_at").Default(time.Now),
    }
}

func (Post) Edges() []ent.Edge {
    return []ent.Edge{
        edge.From("author", User.Type).
            Unique().
            Ref("posts"),
    }
}

生成代码

运行代码生成:

go generate ./...

这将生成大量类型安全的Go代码,用于数据库操作。

创建数据库迁移

安装Atlas工具:

curl -sSf https://atlasgo.sh | sh

生成迁移文件:

atlas migrate diff add_users_posts \
  --dir "file://ent/migrate/migrations" \
  --to "ent://ent/schema" \
  --dev-url "docker://mysql/8/ent"

启动MySQL容器:

docker run --rm --name entdb -d -p 3306:3306 -e MYSQL_DATABASE=ent -e MYSQL_ROOT_PASSWORD=pass mysql:8

应用迁移:

atlas migrate apply --dir file://ent/migrate/migrations \
  --url mysql://root:pass@localhost:3306/ent

第二步:数据库种子数据

安装MySQL驱动:

go get -u github.com/go-sql-driver/mysql

创建main.go并添加种子逻辑:

func seed(ctx context.Context, client *ent.Client) error {
    r, err := client.User.Query().
        Where(user.Name("rotemtam")).
        Only(ctx)
    switch {
    case ent.IsNotFound(err):
        r, err = client.User.Create().
            SetName("rotemtam").
            SetEmail("r@hello.world").
            Save(ctx)
        if err != nil {
            return fmt.Errorf("failed creating user: %v", err)
        }
    case err != nil:
        return fmt.Errorf("failed querying user: %v", err)
    }
    return client.Post.Create().
        SetTitle("Hello, World!").
        SetBody("This is my first post").
        SetAuthor(r).
        Exec(ctx)
}

运行种子程序:

go run main.go -dsn "root:pass@tcp(localhost:3306)/ent?parseTime=true"

第三步:创建首页

视图模板

创建templates/list.tmpl

<html>
<!-- 省略头部内容 -->
<body>
    {{- range . }}
        <h2>{{ .Title }}</h2>
        <p>
            {{ .CreatedAt.Format "2006-01-02" }} by {{ .Edges.Author.Name }}
        </p>
        <p>
            {{ .Body }}
        </p>
    {{- end }}
</body>
</html>

服务器代码

定义服务器结构体:

type server struct {
    client *ent.Client
}

func newServer(client *ent.Client) *server {
    return &server{client: client}
}

添加首页处理器:

func (s *server) index(w http.ResponseWriter, r *http.Request) {
    posts, err := s.client.Post.Query().
        WithAuthor().
        Order(ent.Desc(post.FieldCreatedAt)).
        All(r.Context())
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    if err := tmpl.Execute(w, posts); err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

路由设置

func main() {
    // ...之前的代码
    
    srv := newServer(client)
    http.HandleFunc("/", srv.index)
    
    log.Println("listening on :8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatalf("http server terminated: %v", err)
    }
}

总结

通过本教程,我们使用Ent框架构建了一个简单的CMS系统,涵盖了从数据模型定义、数据库迁移到Web界面开发的完整流程。Ent的类型安全特性和代码生成能力大大简化了Go应用程序的数据访问层开发,同时保持了高性能和灵活性。

对于想要进一步探索Ent的开发者,可以考虑添加以下功能:

  1. 用户认证系统
  2. 文章评论功能
  3. 文章分类和标签
  4. 分页和搜索功能

Ent框架的强大功能使得这些扩展变得简单而高效,是构建数据密集型Go应用的理想选择。

ent ent 项目地址: https://gitcode.com/gh_mirrors/ent4/ent

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颜钥杉Harriet

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值