<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【GoCN酷Go推薦】簡(jiǎn)單強(qiáng)大ORM框架entgo

          共 12524字,需瀏覽 26分鐘

           ·

          2021-04-19 15:41

          簡(jiǎn)介

          ent 是一個(gè)簡(jiǎn)單而又強(qiáng)大的Go實(shí)體框架,便于構(gòu)建和使用大型數(shù)據(jù)模型時(shí)能夠遵循以下原則:

          • 簡(jiǎn)單地使用數(shù)據(jù)庫(kù)結(jié)構(gòu)作為圖結(jié)構(gòu)。
          • 使用Go代碼定義結(jié)構(gòu)。
          • 基于代碼生成的靜態(tài)類型。
          • 容易地進(jìn)行數(shù)據(jù)庫(kù)查詢和圖遍歷。
          • 容易地使用Go模板擴(kuò)展和自定義。

          應(yīng)用場(chǎng)景 

          entgo非常適合處理各種復(fù)雜的關(guān)系,定義好實(shí)體和實(shí)體之間的關(guān)系,就可以快速得到各種想要的數(shù)據(jù)


          核心概念 

          Schema:描述一個(gè)實(shí)體的定義以及他與其他實(shí)體的關(guān)系

            Edges:實(shí)體與實(shí)體之間的關(guān)系稱為edge

          如何使用

          安裝

          go get entgo.io/ent/cmd/ent

          創(chuàng)建Schema

          ent init --target internal/ent/schema User

          運(yùn)行之后會(huì)在internal/ent/schema目錄下生成一個(gè)user.go文件,并進(jìn)行編輯:

          package schema

          import (
           "entgo.io/ent"
           "entgo.io/ent/schema/edge"
           "entgo.io/ent/schema/field"
          )

          // User holds the schema definition for the User entity.
          type User struct {
           ent.Schema
          }

          // Fields of the User.
          func (User) Fields() []ent.Field {
            return []ent.Field{
              // 年齡是自然數(shù)
              field.Int("age").Positive(),
              field.String("name").Default("unknown"),
            }
          }

          // Edges of the User.
          func (User) Edges() []ent.Edge {
           return []ent.Edge{
              
            }
          }

          生成代碼

          ent generate ./internal/ent/schema

          運(yùn)行之后會(huì)自動(dòng)創(chuàng)建以下文件:

          ent
          ├── client.go
          ├── config.go
          ├── context.go
          ├── ent.go
          ├── migrate
          │   ├── migrate.go
          │   └── schema.go
          ├── predicate
          │   └── predicate.go
          ├── schema
          │   └── user.go
          ├── tx.go
          ├── user
          │   ├── user.go
          │   └── where.go
          ├── user.go
          ├── user_create.go
          ├── user_delete.go
          ├── user_query.go
          └── user_update.go

          創(chuàng)建實(shí)體

          package main

          import (
              "context"
              "log"

              "<project>/ent"

              _ "github.com/mattn/go-sqlite3"
          )

          func main() {
              client, err := ent.Open("sqlite3""file:ent?mode=memory&cache=shared&_fk=1")
              if err != nil {
                  log.Fatalf("failed opening connection to sqlite: %v", err)
              }
              defer client.Close()
              // Run the auto migration tool.
              if err := client.Schema.Create(context.Background()); err != nil {
                  log.Fatalf("failed creating schema resources: %v", err)
              }
          }

          有了實(shí)體就可以進(jìn)行增刪改查了

          新增:

          func CreateUser(ctx context.Context, client *ent.Client) (*ent.User, error) {
              u, err := client.User.
                  Create().
                  SetAge(30).
                  SetName("a8m").
                  Save(ctx)
              if err != nil {
                  return nil, fmt.Errorf("failed creating user: %w", err)
              }
              log.Println("user was created: ", u)
              return u, nil
          }

          修改:

          func UpdateUser(ctx context.Context, a8m *ent.User) (*ent.User, error) {
              u, err := a8m.
                  Update().
                  SetAge(28).
                  SetName("neta").
                  Save(ctx)
              if err != nil {
                  return nil, fmt.Errorf("failed update user: %w", err)
              }
              log.Println("user was updated: ", u)
              return u, nil
          }

          刪除:

          func DeleteUser(ctx context.Context, client *ent.Client, a8m *ent.User) error {
              err := client.User.
                  DeleteOne(u).
                  Save(ctx)
              if err != nil {
                  return fmt.Errorf("failed delete user: %w", err)
              }
              log.Println("user was deleted: ", u)
              return nil
          }

          查詢:

          func QueryUser(ctx context.Context, client *ent.Client) (*ent.User, error) {
              u, err := client.User.
                  Query().
                  Where(user.NameEQ("a8m")).
                  // `Only` 在 找不到用戶 或 找到多于一個(gè)用戶 時(shí)報(bào)錯(cuò),
                  Only(ctx)
              if err != nil {
                  return nil, fmt.Errorf("failed querying user: %w", err)
              }
              log.Println("user returned: ", u)
              return u, nil
          }

          Edges:

          建立一個(gè)新的實(shí)體Car,User有多個(gè)CarCar屬于某個(gè)User

          er-user-cars

          文件car.go:

          package schema

          import (
           "entgo.io/ent"
           "entgo.io/ent/schema/edge"
           "entgo.io/ent/schema/field"
          )

          // Car holds the schema definition for the Car entity.
          type Car struct {
           ent.Schema
          }

          // Fields of the Car.
          func (Car) Fields() []ent.Field {
           return []ent.Field{
            field.String("model"),
            field.Time("registered_at"),
           }
          }

          // Edges of the Car.
          func (Car) Edges() []ent.Edge {
           return []ent.Edge{
            edge.
             From("owner", User.Type).
             Ref("cars").
             Unique(),
           }
          }

          修改user.go

          package schema

          import (
           "entgo.io/ent"
           "entgo.io/ent/schema/edge"
           "entgo.io/ent/schema/field"
           "entgo.io/ent/schema/mixin"
          )

          // User holds the schema definition for the User entity.
          type User struct {
           ent.Schema
          }

          // Fields of the User.
          func (User) Fields() []ent.Field {
            return []ent.Field{
              field.Int("age").Positive(),
              field.String("name").Default("unknown"),
            }
          }

          // Edges of the User.
          func (User) Edges() []ent.Edge {
           return []ent.Edge{
              edge.To("cars", Car.Type),
            }
          }

          建立好關(guān)系之后,創(chuàng)建2輛汽車并將他們添加到某個(gè)用戶:

          func CreateCars(ctx context.Context, client *ent.Client) (*ent.User, error) {
              // 創(chuàng)建一輛車型為 "Tesla" 的汽車.
              tesla, err := client.Car.
                  Create().
                  SetModel("Tesla").
                  SetRegisteredAt(time.Now()).
                  Save(ctx)
              if err != nil {
                  return nil, fmt.Errorf("failed creating car: %w", err)
              }
              log.Println("car was created: ", tesla)

              // 創(chuàng)建一輛車型為 "Ford" 的汽車.
              ford, err := client.Car.
                  Create().
                  SetModel("Ford").
                  SetRegisteredAt(time.Now()).
                  Save(ctx)
              if err != nil {
                  return nil, fmt.Errorf("failed creating car: %w", err)
              }
              log.Println("car was created: ", ford)

              // 新建一個(gè)用戶,將兩輛車添加到他的名下
              a8m, err := client.User.
                  Create().
                  SetAge(30).
                  SetName("a8m").
                  AddCars(tesla, ford).
                  Save(ctx)
              if err != nil {
                  return nil, fmt.Errorf("failed creating user: %w", err)
              }
              log.Println("user was created: ", a8m)
              return a8m, nil
          }

          查詢某人擁有的cars:

          import (
              "log"

              "<project>/ent"
              "<project>/ent/car"
          )

          func QueryCars(ctx context.Context, a8m *ent.User) error {
              cars, err := a8m.QueryCars().All(ctx)
              if err != nil {
                  return fmt.Errorf("failed querying user cars: %w", err)
              }
              log.Println("returned cars:", cars)

              // 篩選特定汽車的情況
              ford, err := a8m.QueryCars().
                  Where(car.ModelEQ("Ford")).
                  Only(ctx)
              if err != nil {
                  return fmt.Errorf("failed querying user cars: %w", err)
              }
              log.Println(ford)
              return nil
          }

          查詢汽車們屬于誰(shuí):

          import (
              "fmt"
              "log"

              "<project>/ent"
          )

          func QueryCarUsers(ctx context.Context, a8m *ent.User) error {
              cars, err := a8m.QueryCars().All(ctx)
              if err != nil {
                  return fmt.Errorf("failed querying user cars: %w", err)
              }
              // Query the inverse edge.
              for _, ca := range cars {
                  owner, err := ca.QueryOwner().Only(ctx)
                  if err != nil {
                      return fmt.Errorf("failed querying car %q owner: %w", ca.Model, err)
                  }
                  log.Printf("car %q owner: %q\n", ca.Model, owner.Name)
              }
              return nil
          }

          更多示例參考:https://github.com/ent/ent/tree/master/examples/start

          更多文檔查閱官網(wǎng):https://entgo.io/zh/docs/getting-started

          總結(jié)
          entgo與傳統(tǒng)orm不太一樣,通過(guò)自動(dòng)生成的代碼可以很方便的進(jìn)行數(shù)據(jù)庫(kù)查詢和圖遍歷,使用起來(lái)簡(jiǎn)單清晰,可以很好的協(xié)助我們完成數(shù)據(jù)建模工作。

          還想了解更多嗎?

              更多請(qǐng)查看:https://github.com/google/wire

              歡迎加入我們GOLANG中國(guó)社區(qū):https://gocn.vip/


          《酷Go推薦》招募:


          各位Gopher同學(xué),最近我們社區(qū)打算推出一個(gè)類似GoCN每日新聞的新欄目《酷Go推薦》,主要是每周推薦一個(gè)庫(kù)或者好的項(xiàng)目,然后寫一點(diǎn)這個(gè)庫(kù)使用方法或者優(yōu)點(diǎn)之類的,這樣可以真正的幫助到大家能夠?qū)W習(xí)到新的庫(kù),并且知道怎么用。


          大概規(guī)則和每日新聞?lì)愃?,如果?bào)名人多的話每個(gè)人一個(gè)月輪到一次,歡迎大家報(bào)名!


          點(diǎn)擊 閱讀原文 即刻報(bào)名


          — 往期回顧 —

          【GoCN酷Go推薦】Go程序配置利器-viper庫(kù)

          【GoCN酷Go推薦】Validator 網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)驗(yàn)證包

          【GoCN酷Go推薦】ip2location 解析 IP 地址庫(kù)



          瀏覽 75
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本黄色自拍视频 | 最新日本三级 | 一起操电影网 | 精品日产乱码久久久 | 亚洲AV无码久久精品蜜桃小说 |