1. Memasang alat ent
Untuk memasang alat generasi kode ent
, Anda perlu mengikuti langkah-langkah berikut:
Pertama, pastikan sistem Anda sudah memiliki lingkungan bahasa Go terpasang. Kemudian, jalankan perintah berikut untuk mendapatkan alat ent
:
go get -d entgo.io/ent/cmd/ent
Perintah ini akan mengunduh kode untuk alat ent
, namun tidak akan segera mengkompilasi dan memasangnya. Jika Anda ingin memasang ent
ke direktori $GOPATH/bin
agar dapat menggunakannya di mana saja, Anda juga perlu menjalankan perintah berikut:
go install entgo.io/ent/cmd/ent
Setelah pemasangan selesai, Anda dapat memeriksa apakah alat ent
terpasang dengan benar dan melihat perintah-perintah yang tersedia dengan menjalankan ent -h
.
2. Menginisialisasi Skema
2.1 Menginisialisasi Templat Menggunakan ent init
Membuat file skema baru adalah langkah pertama untuk mulai menggunakan ent
untuk generasi kode. Anda dapat menginisialisasi templat skema dengan menjalankan perintah berikut:
go run -mod=mod entgo.io/ent/cmd/ent new User Pet
Perintah ini akan membuat dua file skema baru: user.go
dan pet.go
, dan menempatkannya di direktori ent/schema
. Jika direktori ent
belum ada, perintah ini juga akan membuatnya secara otomatis.
Menjalankan perintah ent init
di direktori akar proyek adalah praktik yang baik, karena membantu menjaga struktur direktori proyek agar jelas.
2.2 Struktur File Skema
Di dalam direktori ent/schema
, setiap skema sesuai dengan sebuah file sumber bahasa Go. File skema merupakan tempat di mana Anda mendefinisikan model database, termasuk bidang-bidang dan relasi (hubungan).
Sebagai contoh, di file user.go
, Anda mungkin akan mendefinisikan model pengguna, termasuk bidang seperti nama pengguna dan usia, serta mendefinisikan hubungan antara pengguna dan hewan peliharaan. Begitu pula di file pet.go
, Anda akan mendefinisikan model hewan peliharaan beserta bidang-bidang terkait, seperti nama hewan peliharaan, jenisnya, dan hubungan antara hewan peliharaan dan pengguna.
File-file ini pada akhirnya akan digunakan oleh alat ent
untuk menghasilkan kode Go yang sesuai, termasuk kode klien untuk operasi-operasi database dan CRUD (Create, Read, Update, Delete).
// ent/schema/user.go
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema/field"
)
// User mendefinisikan skema untuk entitas Pengguna.
type User struct {
ent.Schema
}
// Metode Fields digunakan untuk mendefinisikan bidang-bidang entitas.
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("name").Unique(),
field.Int("age").Positive(),
}
}
// Metode Edges digunakan untuk mendefinisikan asosiasi-asosiasi entitas.
func (User) Edges() []ent.Edge {
// Asosiasi akan dijelaskan lebih detail pada bagian selanjutnya.
}
File skema ent
menggunakan tipe dan fungsi bahasa Go untuk mendeklarasikan struktur model database, termasuk bidang dan hubungan antara model, serta menggunakan API yang disediakan oleh kerangka kerja ent
untuk mendefinisikan struktur-struktur ini. Pendekatan ini membuat ent
sangat intuitif dan mudah untuk diperluas, sambil juga memanfaatkan ketahanan tipe dari bahasa Go.
3.1 Menjalankan Generasi Kode
Menjalankan ent generate
untuk menghasilkan kode adalah langkah penting dalam kerangka kerja ent
. Dengan perintah ini, ent
akan menghasilkan file kode Go yang sesuai berdasarkan skema-skhema yang telah didefinisikan, memudahkan pekerjaan pengembangan selanjutnya. Perintah untuk menjalankan generasi kode sangatlah mudah:
go generate ./ent
Perintah di atas perlu dijalankan di dalam direktori akar proyek. Saat go generate
dipanggil, ia akan mencari semua file Go yang berisi anotasi-anotasi spesifik dan menjalankan perintah-perintah yang ditentukan dalam anotasi tersebut. Dalam contoh kita, perintah ini menentukan generator kode untuk ent
.
Pastikan inisialisasi skema dan penambahan bidang yang diperlukan telah selesai sebelum menjalankannya. Barulah kode yang dihasilkan akan mencakup semua bagian yang diperlukan.
3.2 Memahami Aset Kode yang Dihasilkan
Aset kode yang dihasilkan berisi beberapa komponen, masing-masing dengan fungsi yang berbeda:
-
Objek Klien dan Tx: Digunakan untuk berinteraksi dengan grafik data. Klien menyediakan metode untuk membuat transaksi (Tx) atau langsung melakukan operasi database.
-
CRUD builders: Untuk setiap tipe skema, ia menghasilkan pembuat untuk membuat, membaca, memperbarui, dan menghapus, menyederhanakan logika operasi entitas yang sesuai.
-
Objek Entitas (Go struct): Ini menghasilkan Go struct yang sesuai untuk setiap tipe dalam skema, memetakan struct ini ke tabel-tabel dalam database.
-
Package Konstan dan Predikat: Berisi konstan dan predikat untuk berinteraksi dengan pembuat.
-
Package Migrasi: Sebuah package untuk migrasi database, cocok untuk dialek-dialek SQL.
-
Package Hook: Menyediakan fungsionalitas untuk menambahkan middleware perubahan, memungkinkan logika kustom dieksekusi sebelum atau sesudah membuat, memperbarui, atau menghapus entitas.
Dengan memeriksa kode yang dihasilkan, Anda dapat memperoleh pemahaman yang lebih dalam tentang bagaimana kerangka kerja ent
mengotomatisasi kode akses data untuk skema Anda.
4. Opsi Pembangkitan Kode
Perintah ent generate
mendukung berbagai opsi untuk menyesuaikan proses pembangkitan kode. Anda dapat memeriksa semua opsi pembangkitan yang didukung melalui perintah berikut:
ent generate -h
Berikut adalah beberapa opsi baris perintah yang sering digunakan:
-
--fitur strings
: Memperluas pembangkitan kode, menambahkan fungsionalitas tambahan. -
--header string
: Melakukan override pada file header pembangkitan kode. -
--storage string
: Menentukan driver penyimpanan yang didukung dalam pembangkitan kode, defaultnya adalah "sql". -
--target string
: Menentukan direktori target untuk pembangkitan kode. -
--template strings
: Menjalankan templat Go tambahan. Mendukung berkas, direktori, dan jalur wildcard, misalnya:--template file="path/to/file.tmpl"
.
Opsi-opsi ini memungkinkan pengembang untuk menyesuaikan proses pembangkitan kode mereka sesuai dengan berbagai kebutuhan dan preferensi.
5. Konfigurasi Opsi Penyimpanan
ent
mendukung pembangkitan aset kode untuk dialek SQL dan Gremlin, dengan defaultnya adalah dialek SQL. Jika proyek memerlukan koneksi ke database Gremlin, dialek database yang sesuai perlu dikonfigurasi. Berikut adalah cara untuk menentukan opsi penyimpanan:
ent generate --storage gremlin ./ent/schema
Perintah di atas memerintahkan ent
untuk menggunakan dialek Gremlin saat melakukan pembangkitan kode. Hal ini memastikan bahwa aset yang dihasilkan disesuaikan dengan persyaratan database Gremlin, memastikan kompatibilitas dengan database grafik tertentu.
6. Penggunaan Lanjutan: Paket entc
6.1 Penggunaan entc
sebagai Paket dalam Proyek
entc
adalah paket inti yang digunakan untuk pembangkitan kode dalam kerangka kerja ent
. Selain dari alat baris perintah, entc
juga dapat diintegrasikan ke dalam proyek sebagai sebuah paket, memungkinkan pengembang untuk mengendalikan dan menyesuaikan proses pembangkitan kode dalam kode itu sendiri.
Untuk menggunakan entc
sebagai paket dalam proyek, Anda perlu membuat sebuah berkas bernama entc.go
dan menambahkan konten berikut ke dalam berkas tersebut:
// +build ignore
package main
import (
"log"
"entgo.io/ent/entc"
"entgo.io/ent/entc/gen"
)
func main() {
if err := entc.Generate("./schema", &gen.Config{}); err != nil {
log.Fatal("running ent codegen:", err)
}
}
Dengan pendekatan ini, Anda dapat memodifikasi struktur gen.Config
dalam fungsi main
untuk menerapkan berbagai opsi konfigurasi. Dengan memanggil fungsi entc.Generate
sesuai kebutuhan, Anda dapat mengendalikan proses pembangkitan kode secara fleksibel.
6.2 Konfigurasi Detail dari entc
entc
menyediakan beragam opsi konfigurasi yang memungkinkan pengembang untuk menyesuaikan kode yang dihasilkan. Misalnya, hook kustom dapat dikonfigurasi untuk memeriksa atau memodifikasi kode yang dihasilkan, dan dependensi eksternal dapat dimasukkan menggunakan dependency injection.
Contoh berikut ini menunjukkan bagaimana menyediakan hook kustom untuk fungsi entc.Generate
:
func main() {
err := entc.Generate("./schema", &gen.Config{
Hooks: []gen.Hook{
HookFunction,
},
})
if err != nil {
log.Fatalf("error saat menjalankan ent codegen: %v", err)
}
}
// HookFunction merupakan fungsi hook kustom
func HookFunction(next gen.Generator) gen.Generator {
return gen.GenerateFunc(func(g *gen.Graph) error {
// Dapat menangani mode graf yang diwakili oleh g di sini
// Misalnya, memvalidasi keberadaan bidang atau memodifikasi struktur
return next.Generate(g)
})
}
Selain itu, dependensi eksternal dapat ditambahkan menggunakan entc.Dependency
:
func main() {
opts := []entc.Option{
entc.Dependency(
entc.DependencyType(&http.Client{}),
),
entc.Dependency(
entc.DependencyName("Writer"),
entc.DependencyTypeInfo(&field.TypeInfo{
Ident: "io.Writer",
PkgPath: "io",
}),
),
}
if err := entc.Generate("./schema", &gen.Config{}, opts...); err != nil {
log.Fatalf("error saat menjalankan ent codegen: %v", err)
}
}
Dalam contoh ini, kami menyuntikkan http.Client
dan io.Writer
sebagai dependensi ke objek klien yang dihasilkan.
7. Output dari Deskripsi Skema
Dalam kerangka kerja ent
, perintah ent describe
dapat digunakan untuk menghasilkan deskripsi skema dalam format grafis. Hal ini dapat membantu pengembang memahami dengan cepat entitas dan hubungan yang ada.
Jalankan perintah berikut ini untuk mendapatkan deskripsi skema:
go run -mod=mod entgo.io/ent/cmd/ent describe ./ent/schema
Perintah di atas akan menghasilkan tabel yang mirip dengan berikut, menampilkan informasi seperti bidang, tipe, hubungan, dll. untuk setiap entitas:
User:
+-------+---------+--------+-----------+ ...
| Bidang| Tipe | Unik | Opsional | ...
+-------+---------+--------+-----------+ ...
| id | int | false | false | ...
| name | string | true | false | ...
+-------+---------+--------+-----------+ ...
+-------+--------+---------+-----------+ ...
| Edge | Tipe | Invers | Relasi | ...
+-------+--------+---------+-----------+ ...
| pets | Pet | false | O2M | ...
+-------+--------+---------+-----------+ ...
8. Hook untuk Generasi Kode
8.1 Konsep Hook
Hook adalah fungsi middleware yang dapat dimasukkan ke dalam proses generasi kode ent
, memungkinkan logika kustom dimasukkan sebelum dan sesudah menghasilkan kode. Hook dapat digunakan untuk memanipulasi abstract syntax tree (AST) dari kode yang dihasilkan, melakukan validasi, atau menambahkan potongan kode tambahan.
8.2 Contoh Penggunaan Hook
Berikut adalah contoh penggunaan hook untuk memastikan bahwa semua bidang mengandung tag struktur tertentu (misalnya, json
):
func main() {
err := entc.Generate("./schema", &gen.Config{
Hooks: []gen.Hook{
EnsureStructTag("json"),
},
})
if err != nil {
log.Fatalf("error saat menjalankan ent codegen: %v", err)
}
}
// EnsureStructTag memastikan bahwa semua bidang dalam graf mengandung tag struktur spesifik
func EnsureStructTag(name string) gen.Hook {
return func(next gen.Generator) gen.Generator {
return gen.GenerateFunc(func(g *gen.Graph) error {
for _, node := range g.Nodes {
for _, field := range node.Fields {
tag := reflect.StructTag(field.StructTag)
if _, ok := tag.Lookup(name); !ok {
return fmt.Errorf("tag struktur %q tidak ada untuk bidang %s.%s", name, node.Name, field.Name)
}
}
}
return next.Generate(g)
})
}
}
Dalam contoh ini, sebelum menghasilkan kode, fungsi EnsureStructTag
memeriksa setiap bidang untuk tag json
. Jika suatu bidang tidak memiliki tag ini, maka generasi kode akan dihentikan dan menghasilkan error. Ini merupakan cara yang efektif untuk menjaga kebersihan dan konsistensi kode.