Golangにおけるentを解説する



---

# Go の強力な ORM「ent」を徹底解説！【入門から実践まで】

## 1. **`ent` とは？**
[`ent`](https://entgo.io/) は Facebook（Meta）によって開発された **Go のエンティティ駆動 ORM（Object-Relational Mapper）** です。  
GORM などの ORM と比べて **静的型安全** や **コード生成** を重視しており、高速かつ堅牢なデータモデルを構築できます。

### **特徴**
✅ **型安全性**: Go の型システムを活用し、SQL クエリのエラーをコンパイル時に検出  
✅ **コード生成**: スキーマ定義から自動生成されるため、開発効率が向上  
✅ **リレーション対応**: 1対多、多対多などのリレーションをシンプルに扱える  
✅ **高パフォーマンス**: GORM よりも高速なクエリを生成  
✅ **GraphQL / REST API との統合**: 簡単にエンティティを API にマッピング可能  

---

## 2. **`ent` のインストール**
まずは `ent` をプロジェクトに導入しましょう。

```sh
go get entgo.io/ent/cmd/ent
go install entgo.io/ent/cmd/ent
```

その後、スキーマを格納する `ent/schema` ディレクトリを作成します。

```sh
mkdir -p ent/schema
```

---

## 3. **スキーマの定義**
`ent` は **スキーマ（schema）** を Go の構造体として定義し、そこから ORM のコードを生成します。

例として、**ユーザー（User）モデル** を作成します。

```sh
ent new User
```

すると、`ent/schema/User.go` が生成されます。  
このファイルを編集して、データベースのカラムを定義します。

```go
package schema

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

// User スキーマの定義
type User struct {
	ent.Schema
}

// Fields は User テーブルのカラムを定義
func (User) Fields() []ent.Field {
	return []ent.Field{
		field.Int("id"),
		field.String("name").NotEmpty(),
		field.String("email").Unique(),
		field.Int("age").Positive(),
	}
}
```

---

## 4. **コードの生成**
スキーマ定義後、`ent` のコードを生成します。

```sh
go run entgo.io/ent/cmd/ent generate ./ent/schema
```

これにより、以下のようなファイルが自動生成されます。

```
ent/
├── client.go
├── user/
│   ├── user.go
│   ├── user_create.go
│   ├── user_query.go
│   ├── user_update.go
│   ├── user_delete.go
│   └── user_hooks.go
└── runtime.go
```

この `ent.Client` を使って、DB 操作ができるようになります。

---

## 5. **データベースのセットアップ**
`ent` は **PostgreSQL、MySQL、SQLite** など複数のデータベースをサポートしています。

まず、`go-sqlite3` などのドライバをインストールしましょう。（今回は SQLite を使用）

```sh
go get github.com/mattn/go-sqlite3
```

次に、DB に接続するための `main.go` を作成します。

```go
package main

import (
	"context"
	"log"

	"example.com/ent_sample/ent"
	_ "github.com/mattn/go-sqlite3"
)

func main() {
	// SQLite に接続
	client, err := ent.Open("sqlite3", "file:ent.db?mode=memory&cache=shared&_fk=1")
	if err != nil {
		log.Fatalf("failed to connect to database: %v", err)
	}
	defer client.Close()

	// DB のマイグレーション
	ctx := context.Background()
	if err := client.Schema.Create(ctx); err != nil {
		log.Fatalf("failed to create schema: %v", err)
	}

	log.Println("Database schema created successfully!")
}
```

これで `go run main.go` を実行すると、スキーマが DB に作成されます。

---

## 6. **CRUD 操作（作成・取得・更新・削除）**

### **6.1 データの作成**
```go
user, err := client.User.Create().
	SetName("Taro").
	SetEmail("taro@example.com").
	SetAge(25).
	Save(ctx)
if err != nil {
	log.Fatalf("failed to create user: %v", err)
}
log.Println("User created:", user)
```

---

### **6.2 データの取得**
```go
user, err := client.User.Query().
	Where(user.Email("taro@example.com")).
	Only(ctx)
if err != nil {
	log.Fatalf("failed to fetch user: %v", err)
}
log.Println("User found:", user)
```

---

### **6.3 データの更新**
```go
updatedUser, err := client.User.UpdateOneID(user.ID).
	SetAge(30).
	Save(ctx)
if err != nil {
	log.Fatalf("failed to update user: %v", err)
}
log.Println("User updated:", updatedUser)
```

---

### **6.4 データの削除**
```go
err := client.User.DeleteOneID(user.ID).Exec(ctx)
if err != nil {
	log.Fatalf("failed to delete user: %v", err)
}
log.Println("User deleted successfully!")
```

---

## 7. **リレーション（1対多、多対多）**
`ent` では、**テーブルのリレーション** も簡単に定義できます。

たとえば、`User` と `Post`（投稿）の **1対多** 関係を作成するとします。

```sh
ent new Post
```

次に、`Post` スキーマを編集します。

```go
package schema

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

// Post スキーマ
type Post struct {
	ent.Schema
}

func (Post) Fields() []ent.Field {
	return []ent.Field{
		field.String("title"),
		field.String("content"),
	}
}

// ユーザーとの関係を定義（1対多）
func (Post) Edges() []ent.Edge {
	return []ent.Edge{
		edge.From("author", User.Type).
			Ref("posts").
			Unique(),
	}
}
```

このように **`edge.From()` を使ってリレーションを定義** できます。

---

## まとめ
`ent` を使うと、**型安全な ORM** を簡単に実装できます。  
特に **コード生成の仕組み** により、エンティティの管理がしやすく、GORM よりも高パフォーマンスな設計が可能です。

### **学んだポイント**
✅ `ent` は Go 向けの強力な ORM  
✅ `ent new User` でスキーマを作成  
✅ `ent generate` でコードを自動生成  
✅ `ent.Client` で CRUD 操作が可能  
✅ 1対多、多対多のリレーションも簡単に定義  

Golang での ORM に悩んでいる方は、ぜひ `ent` を試してみてください！

---