
Halo semuanya! Ada banyak artikel tentang GraphQL di Habr, tetapi setelah melalui mereka saya menemukan bahwa mereka semua memotong bahasa yang indah seperti Go. Hari ini saya akan mencoba untuk memperbaiki kesalahpahaman ini. Untuk melakukan ini, kami akan menulis API on Go menggunakan GraphQL.
Singkatnya: GraphQL adalah bahasa permintaan untuk membangun API yang menjelaskan dalam bentuk apa untuk meminta dan mengembalikan data (informasi lebih rinci tentang sumber daya resmi graphql.imtqy.com dan tentang hub )
Anda dapat berpendapat bahwa GraphQL atau REST lebih baik di sini.
Kami akan memiliki API klasik: CRUD (Buat, Baca, Perbarui, Hapus) menambah, menerima, mengedit dan menghapus produk di toko online.
Di sisi server, kami akan menggunakan implementasi GraphQL graphql-go yang siap
Pertama Anda perlu mengunduh graphql-go, ini bisa dilakukan dengan perintah
go get github.com/graphql-go/graphql
Selanjutnya, kami menggambarkan struktur produk (dalam bentuk yang disederhanakan)
type Product struct { ID int64 `json:"id"` Name string `json:"name"` Info string `json:"info,omitempty"` Price float64 `json:"price"` }
ID
- pengidentifikasi unik, Name
- nama, Info
- informasi produk, Price
- harga
Hal pertama yang harus dilakukan adalah memanggil metode Do
, yang menerima skema data dan parameter kueri sebagai parameter input. Dan itu akan mengembalikan data yang dihasilkan kepada kami (untuk pengiriman lebih lanjut ke klien)
result := graphql.Do(graphql.Params{ Schema: schema, RequestString: query, })
Kode lengkap func executeQuery(query string, schema graphql.Schema) *graphql.Result { result := graphql.Do(graphql.Params{ Schema: schema, RequestString: query, }) if len(result.Errors) > 0 { fmt.Printf("errors: %v", result.Errors) } return result } func main() { http.HandleFunc("/product", func(w http.ResponseWriter, r *http.Request) { result := executeQuery(r.URL.Query().Get("query"), schema) json.NewEncoder(w).Encode(result) }) http.ListenAndServe(":8080", nil) }
Schema
- skema data, RequestString
- nilai parameter string kueri, dalam kasus kami, nilai query
Skema
Skema menerima dua tipe data root: Query
- data tidak berubah, Mutation
- data dapat berubah
var schema, _ = graphql.NewSchema( graphql.SchemaConfig{ Query: queryType, Mutation: mutationType, }, )
Pertanyaan
Query
digunakan untuk membaca (dan hanya membaca) data. Menggunakan Query
kami menentukan data apa yang harus dikembalikan server.
Kami akan menulis implementasi tipe data Query
, dalam kasus kami ini akan berisi bidang dengan informasi tentang satu produk (produk) dan daftar barang (daftar)
var queryType = graphql.NewObject( graphql.ObjectConfig{ Name: "Query", Fields: graphql.Fields{ "product": &graphql.Field{ Type: productType, Description: "Get product by id",
Jenis queryType berisi Name
dan Fields
diperlukan, serta Description
opsional (digunakan untuk dokumentasi)
Pada gilirannya, bidang Fields
juga berisi bidang Type
diperlukan dan bidang Args
, Resolve
dan Description
opsional
Args (Argumen)
Argumen - daftar parameter yang ditransfer dari klien ke server dan memengaruhi hasil data yang dikembalikan. Argumen terikat pada bidang tertentu. Dan argumennya dapat disampaikan dalam Query
dan Mutation
.
?query={product(id:1){name,info,price}}
Dalam hal ini, argumen id
untuk bidang product
dengan nilai 1 menunjukkan bahwa perlu untuk mengembalikan produk dengan pengidentifikasi yang ditentukan.
Untuk list
argumen dihilangkan, tetapi dalam aplikasi nyata bisa jadi, misalnya: limit
dan offset
.
Putuskan (Pengakuan)
Semua logika bekerja dengan data (misalnya, permintaan basis data, pemrosesan, dan pemfilteran) ada di dalam pengenal, merekalah yang mengembalikan data yang akan dikirim ke klien sebagai respons terhadap permintaan.
Jenis
GraphQL menggunakan sistem tipenya untuk menggambarkan data. Anda dapat menggunakan kedua tipe dasar String
, Int
, Float
, Boolean
, dan yang Anda sendiri (custom). Sebagai contoh kita, kita akan membutuhkan Product
tipe kustom, yang akan menggambarkan semua properti produk
var productType = graphql.NewObject( graphql.ObjectConfig{ Name: "Product", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.Int, }, "name": &graphql.Field{ Type: graphql.String, }, "info": &graphql.Field{ Type: graphql.String, }, "price": &graphql.Field{ Type: graphql.Float, }, }, }, )
Untuk setiap bidang, tipe dasar ditentukan, dalam hal ini graphql.Int
, graphql.String
, graphql.Float
.
Jumlah bidang bersarang tidak terbatas, sehingga Anda dapat menerapkan sistem grafik dari level apa pun.
Mutasi
Mutasi adalah data yang dapat diubah ini, yang meliputi: penambahan, pengeditan, dan penghapusan. Jika tidak, mutasi sangat mirip dengan kueri reguler: mereka juga mengambil argumen Args
dan mengembalikan Resolve
data sebagai respons terhadap kueri.
Mari kita menulis mutasi untuk produk kita. var mutationType = graphql.NewObject(graphql.ObjectConfig{ Name: "Mutation", Fields: graphql.Fields{ "create": &graphql.Field{ Type: productType, Description: "Create new product", Args: graphql.FieldConfigArgument{ "name": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.String),
Semua mirip dengan queryType
. Hanya ada satu fitur kecil, ketik graphql.NewNonNull(graphql.Int)
, yang memberitahu kita bahwa bidang ini tidak boleh kosong (mirip dengan NOT NULL
di MySQL)
Itu saja. Sekarang kami memiliki API Go CRUD sederhana untuk bekerja dengan barang. Kami tidak menggunakan database untuk contoh ini, tetapi kami melihat cara membuat model data dan memanipulasi mereka menggunakan mutasi.
Contohnya
Jika Anda mengunduh sumber melalui
go get github.com/graphql-go/graphql
buka saja direktori dengan sebuah contoh
cd examples/crud
dan jalankan aplikasi
go run main.go
Anda dapat menggunakan pertanyaan berikut:
Mendapatkan produk dengan ID
http://localhost:8080/product?query={product(id:1){name,info,price}}
Mendapatkan daftar produk
http://localhost:8080/product?query={list{id,name,info,price}}
Tambahkan Produk Baru
http://localhost:8080/product?query=mutation+_{create(name:"Tequila",info:"Strong alcoholic beverage",price:999){id,name,info,price}}
Pengeditan produk
http://localhost:8080/product?query=mutation+_{update(id:1,price:195){id,name,info,price}}
Menghapus produk dengan id
http://localhost:8080/product?query=mutation+_{delete(id:1){id,name,info,price}}
Jika Anda menggunakan REST, perhatikan GraphQL sebagai alternatif yang memungkinkan. Ya, pada pandangan pertama sepertinya lebih sulit, tetapi ada baiknya memulai dan dalam beberapa hari Anda akan menguasai teknologi ini. Setidaknya itu akan bermanfaat.