title: 20 Mengelola Query dengan Parameter di graphql-go
date: 2024-06-26
author: Faris Azhar
tags: [Go, GraphQL, Back-End, API, Tutorial]
GraphQL menawarkan fleksibilitas yang luar biasa dalam membangun API modern—termasuk pada pengelolaan query dengan parameter. Bagi backend engineer yang menggunakan Go, package graphql-go
menjadi salah satu pilihan utama. Namun, manajemen parameter pada query GraphQL kadang menjadi stumbling block tersendiri, baik dari segi desain schema maupun implementasi resolver.
Dalam tulisan ini, saya akan mengupas tuntas perihal pengelolaan query dengan parameter menggunakan graphql-go
, dilengkapi 20 best practices dan trik penting. Kita akan bahas baik secara konseptual, praktik kode, hingga contoh real-world yang berkaitan dengan filtering, pagination, validasi, dan error handling.
1. Menentukan Parameter di Skema Schema
Hal pertama adalah memahami letak parameter dalam schema GraphQL. Parameter disematkan sebagai argument pada field:
userType := graphql.NewObject(graphql.ObjectConfig{
Name: "User",
Fields: graphql.Fields{
"id": &graphql.Field{Type: graphql.String},
"name": &graphql.Field{Type: graphql.String},
},
})
queryType := graphql.NewObject(graphql.ObjectConfig{
Name: "Query",
Fields: graphql.Fields{
"user": &graphql.Field{
Type: userType,
Args: graphql.FieldConfigArgument{
"id": &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String),
},
},
Resolve: userResolver,
},
},
})
Dengan skema di atas, klien dapat melakukan query seperti:
{
user(id: "1") {
name
}
}
2. Penggunaan Default Value pada Argument
Argument bisa diberikan default value, sehingga tidak wajib selalu diberikan oleh klien:
"status": &graphql.ArgumentConfig{
Type: graphql.String,
DefaultValue: "active",
},
3. Mendefinisikan Argument Kompleks (Input Object)
Untuk parameter lebih kompleks, gunakan Object Input Type:
userFilterInput := graphql.NewInputObject(graphql.InputObjectConfig{
Name: "UserFilter",
Fields: graphql.InputObjectConfigFieldMap{
"name": &graphql.InputObjectFieldConfig{Type: graphql.String},
"age": &graphql.InputObjectFieldConfig{Type: graphql.Int},
},
})
"users": &graphql.Field{
Type: graphql.NewList(userType),
Args: graphql.FieldConfigArgument{
"filter": &graphql.ArgumentConfig{Type: userFilterInput},
},
Resolve: usersResolver,
}
4. Mengambil Parameter di Resolver
Argument didapatkan lewat params.Args
dalam resolver:
func userResolver(p graphql.ResolveParams) (interface{}, error) {
id, ok := p.Args["id"].(string)
if !ok {
return nil, errors.New("ID is required")
}
// Query ke database
}
5. Validasi Argument
Selalu lakukan validasi sebelum meneruskan param ke proses selanjutnya.
if len(id) != 36 {
return nil, errors.New("Invalid ID format")
}
6. Parameter Optional dan Nullables
Kesalahan umum terjadi ketika parameter optional tidak dicek nilainya (ada di params.Args
atau tidak).
var name string
if n, exists := p.Args["name"]; exists {
name = n.(string)
}
7. Filtering Multi-Field
Izinkan filter dengan array/daftar pada argument.
"tags": &graphql.ArgumentConfig{
Type: graphql.NewList(graphql.String),
},
8. Implementasi Pagination
Pagination sangat umum. Manfaatkan parameter limit
dan offset
:
"users": &graphql.Field{
Type: graphql.NewList(userType),
Args: graphql.FieldConfigArgument{
"limit": &graphql.ArgumentConfig{Type: graphql.Int, DefaultValue: 10},
"offset": &graphql.ArgumentConfig{Type: graphql.Int, DefaultValue: 0},
},
Resolve: usersResolver,
}
9. Parameter Enum
Definisikan tipe Enum agar pemanggil hanya bisa memilih nilai valid.
statusEnum := graphql.NewEnum(graphql.EnumConfig{
Name: "Status",
Values: graphql.EnumValueConfigMap{
"ACTIVE": &graphql.EnumValueConfig{Value: "active"},
"INACTIVE": &graphql.EnumValueConfig{Value: "inactive"},
},
})
10. Parameter Nested
Buat input type dalam input type untuk query nested, misal filter dalam filter.
11. Array Parameter
Argument bertipe list, misal multi ID.
"ids": &graphql.ArgumentConfig{
Type: graphql.NewList(graphql.String),
}
12. Input Validation di Resolver
Selain di schema, tambahkan validasi di resolver. Misal cek uniqueness, relasi foreign key, dsb.
13. Simulasi Query dengan Parameter
Mari bandingkan query dengan/ tanpa parameter:
Query | Response |
---|---|
users(limit: 2) | [{"id":"1"}, {"id":"2"}] |
user(id: "xyz") | {"id": "xyz", "name": "Dewi"} |
users(filter: {...}) | [{"id":"a"}, {"id":"b"}] |
14. Penanganan Kesalahan (Error Handling)
Selalu kirim error yang “clear” di resolver ketika validasi gagal.
15. Query Variables
Gunakan query variables alih-alih hard-coded parameter di klien:
query getUser($id: String!) {
user(id: $id) {
name
}
}
16. Dokumentasi Parameter Schema
Manfaatkan deskripsi pada schema, agar dev frontend mudah mengerti argumen yang tersedia.
17. Parameter Query Dinamis
Jika parameter bisa satu dari banyak field (misal filter by email atau username):
Args: graphql.FieldConfigArgument{
"email": &graphql.ArgumentConfig{Type: graphql.String},
"username": &graphql.ArgumentConfig{Type: graphql.String},
}
Di resolver, cek mana argumen terisi.
18. Diagram Alur Proses Parameter Query
Untuk gambaran lebih jelas, berikut flow resolver dalam query dengan parameter di graphql-go
:
graph TD A[Klien Mengirim Query dgn Parameter] --> B[GraphQL Handler Receive] B --> C[Schema Validate Param] C --> D[Resolver Ambil Params] D --> E[Validasi & Filtering di Go] E --> F[Query ke DB] F --> G[Return Response]
19. Response Field Terbatas oleh Parameter
Bisa juga batasi field yang di-query pakai parameter, mirip projection pada SQL/MongoDB.
20. Separation of Concerns
Pisahkan logic handler GraphQL, validasi parameter, data access, dan error handling dalam kode Go Anda.
Kesimpulan
Mengelola query dengan parameter di graphql-go
adalah hal fundamental jika Anda ingin membangun API GraphQL robust, scalable, dan maintainable di Go. Sebagai penutup, berikut tabel ringkasan best practices:
No | Best Practice | Implementation Example |
---|---|---|
1 | Parameter di Schema | Args: FieldConfigArgument{...} |
4 | Param di Resolver | p.Args["param_name"] |
8 | Pagination | Arg limit , offset & validate di Go |
13 | Simulasi Query | Cek hasil berbeda tergantung argumen |
20 | Separation of Concern | Pisahkan handler, validasi, data, error |
Mulailah mengoptimalkan reflectivity implementation Anda, bahkan untuk query-query yang kelihatan trivial sekalipun. Keamanan, efisiensi, dan kemudahan debugging adalah investasi yang sepadan untuk proyek Go Anda berikutnya!
Punya tips lain yang belum dibahas? Tulis di kolom komentar, mari diskusi! 🚀
42 Menggunakan Enum di Protobuf
Artikel Terhangat
42 Menggunakan Enum di Protobuf
07 Jul 2025
19 Implementasi Resolver untuk Query `users`
07 Jul 2025
41 Memahami Nested Messages
07 Jul 2025

42 Menggunakan Enum di Protobuf

19 Implementasi Resolver untuk Query `users`
