25 Menggunakan Interface dan Union Types di graphql-go
GraphQL memberikan fleksibilitas luar biasa dalam mendefinisikan schema API, terutama saat menangani data yang memiliki banyak bentuk (polymorphic). Di antara fitur powerful tersebut, Interface dan Union Types adalah dua alat utama untuk membangun aplikasi yang scalable dan maintainable. Pada artikel kali ini, kita akan membahas secara komprehensif bagaimana menggunakan Interface dan Union Types di graphql-go, library populer untuk membangun GraphQL server di Go.
Apa Itu Interface dan Union Types di GraphQL?
Sebelum bersentuhan dengan graphql-go
, mari kita pahami dulu konsep dasarnya dalam GraphQL.
Interface Type
Interface mirip dengan konsep interface di pemrograman berorientasi objek. Sebuah interface mendefinisikan satu set field yang harus diimplementasikan oleh object type yang mengimplementasinya. Query terhadap interface akan mengembalikan salah satu dari object yang mengimplementasinya.
Contoh sederhana:
interface Character {
id: ID!
name: String!
}
type Human implements Character {
id: ID!
name: String!
homePlanet: String
}
type Droid implements Character {
id: ID!
name: String!
primaryFunction: String
}
Union Type
Union mendefinisikan sebuah type yang bisa berupa salah satu dari beberapa type yang ditentukan, tanpa mewajibkan mereka untuk memiliki field yang sama.
Contoh:
union SearchResult = Human | Droid | Starship
Mengimplementasikan Interface dan Union di graphql-go
Untuk kebutuhan produksi, kita menggunakan package github.com/graphql-go/graphql.
Skenario: Kita membuat API karakter Star Wars yang memiliki dua jenis karakter (Human
dan Droid
) serta sebuah fitur pencarian (search
) yang hasilnya bisa berupa objek Human
, Droid
, atau Starship
.
1. Instalasi
go get github.com/graphql-go/graphql
2. Definisi Interface
Mari kita buat interface Character
.
var characterInterface = graphql.NewInterface(graphql.InterfaceConfig{
Name: "Character",
Fields: graphql.Fields{
"id": &graphql.Field{Type: graphql.NewNonNull(graphql.ID)},
"name": &graphql.Field{Type: graphql.NewNonNull(graphql.String)},
},
ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
switch p.Value.(type) {
case Human:
return humanType
case Droid:
return droidType
default:
return nil
}
},
})
Penjelasan:
ResolveType
adalah fungsi penting untuk runtime type resolution. Ia akan menentukan object mana yang dikembalikan ketika client men-query sebuah interface.
3. Definisi Object Type yang Mengimplementasikan Interface
type Human struct {
ID string `json:"id"`
Name string `json:"name"`
HomePlanet string `json:"homePlanet"`
}
var humanType = graphql.NewObject(graphql.ObjectConfig{
Name: "Human",
Interfaces: []*graphql.Interface{characterInterface},
Fields: graphql.Fields{
"id": &graphql.Field{Type: graphql.NewNonNull(graphql.ID)},
"name": &graphql.Field{Type: graphql.NewNonNull(graphql.String)},
"homePlanet": &graphql.Field{Type: graphql.String},
},
})
type Droid struct {
ID string `json:"id"`
Name string `json:"name"`
PrimaryFunction string `json:"primaryFunction"`
}
var droidType = graphql.NewObject(graphql.ObjectConfig{
Name: "Droid",
Interfaces: []*graphql.Interface{characterInterface},
Fields: graphql.Fields{
"id": &graphql.Field{Type: graphql.NewNonNull(graphql.ID)},
"name": &graphql.Field{Type: graphql.NewNonNull(graphql.String)},
"primaryFunction": &graphql.Field{Type: graphql.String},
},
})
4. Definisi Union Type
Misal kita juga punya tipe Starship:
type Starship struct {
ID string `json:"id"`
Name string `json:"name"`
Model string `json:"model"`
}
var starshipType = graphql.NewObject(graphql.ObjectConfig{
Name: "Starship",
Fields: graphql.Fields{
"id": &graphql.Field{Type: graphql.NewNonNull(graphql.ID)},
"name": &graphql.Field{Type: graphql.NewNonNull(graphql.String)},
"model": &graphql.Field{Type: graphql.String},
},
})
var searchResultUnion = graphql.NewUnion(graphql.UnionConfig{
Name: "SearchResult",
Types: []*graphql.Object{humanType, droidType, starshipType},
ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
switch p.Value.(type) {
case Human:
return humanType
case Droid:
return droidType
case Starship:
return starshipType
default:
return nil
}
},
})
5. Schema GraphQL dan Query
Mari kita susun root query yang menggunakan Interface dan Union:
var rootQuery = graphql.NewObject(graphql.ObjectConfig{
Name: "Query",
Fields: graphql.Fields{
"character": &graphql.Field{
Type: characterInterface,
Args: graphql.FieldConfigArgument{
"id": &graphql.ArgumentConfig{Type: graphql.NewNonNull(graphql.ID)},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
id := p.Args["id"].(string)
if h, ok := humanData[id]; ok {
return h, nil
}
if d, ok := droidData[id]; ok {
return d, nil
}
return nil, nil
},
},
"search": &graphql.Field{
Type: graphql.NewList(searchResultUnion),
Args: graphql.FieldConfigArgument{
"text": &graphql.ArgumentConfig{Type: graphql.NewNonNull(graphql.String)},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
text := p.Args["text"].(string)
// Simulasi pencarian
results := []interface{}{}
for _, h := range humanData {
if strings.Contains(h.Name, text) {
results = append(results, h)
}
}
for _, d := range droidData {
if strings.Contains(d.Name, text) {
results = append(results, d)
}
}
for _, s := range starshipData {
if strings.Contains(s.Name, text) {
results = append(results, s)
}
}
return results, nil
},
},
},
})
6. Contoh Data Dummy
var humanData = map[string]Human{
"1000": {"1000", "Luke Skywalker", "Tatooine"},
}
var droidData = map[string]Droid{
"2000": {"2000", "C-3PO", "Protocol"},
}
var starshipData = map[string]Starship{
"3000": {"3000", "Millennium Falcon", "YT-1300"},
}
Query Contoh
Query untuk interface:
{
character(id: "1000") {
id
name
... on Human {
homePlanet
}
... on Droid {
primaryFunction
}
}
}
Query untuk union:
{
search(text: "Sky") {
... on Human {
id
name
homePlanet
}
... on Droid {
id
name
primaryFunction
}
... on Starship {
id
name
model
}
}
}
7. Alur Eksekusi dengan Interface dan Union
Mari visualisasikan dengan diagram alur menggunakan Mermaid.
flowchart TD Q1([Client Query]) S1([Server]) RT1{Apakah Interface?} RT2{Apakah Union?} TYPE1([Resolve Type]) RESP([Response]) Q1 --> S1 S1 --> RT1 RT1 -- Ya --> TYPE1 RT1 -- Tidak --> RT2 RT2 -- Ya --> TYPE1 RT2 -- Tidak --> RESP TYPE1 --> RESP
8. Tabel Perbandingan Interface vs Union
Aspek | Interface | Union |
---|---|---|
Field yang harus dimiliki | Wajib memiliki field tertentu (sesuai interface) | Tidak wajib punya field yang sama |
Kegunaan utama | Polymorphism dengan field yang seragam | Polymorphism alternatif tanpa field seragam |
Contoh kasus | User: Admin, Guest, Member | Hasil pencarian yang bisa berbagai tipe objek |
9. Testing Endpoint dengan Go
Anda bisa menguji endpoint dengan code berikut:
schema, _ := graphql.NewSchema(graphql.SchemaConfig{
Query: rootQuery,
})
params := graphql.Params{
Schema: schema,
RequestString: `{ search(text: "Sky") { ... on Human { id name homePlanet } } }`,
}
result := graphql.Do(params)
fmt.Printf("%v", result.Data)
Outputnya akan berupa JSON sesuai type yang dikembalikan.
Penutup
Menggunakan Interface dan Union Types di graphql-go membuat API kita lebih fleksibel dan siap menangani kebutuhan bisnis yang kompleks. Dengan pendekatan ini, aplikasi backend Go Anda akan lebih maintainable, scalable, serta mudah diintegrasikan dengan client yang heterogen.
Jika Anda membangun startup atau proyek besar dengan Go, pastikan selalu memanfaatkan fitur schema GraphQL ini. Integrasikan dengan testing, monitoring, dan dokumentasi yang baik agar developer experience seluruh tim selalu terjaga.
Selamat bereksperimen dan membangun API GraphQL yang solid dengan graphql-go
! 🚀
47 Reserved Fields dan Reserved Numbers
48 Custom Options di Protobuf
Artikel Terhangat
26 Apa Itu Mutation dan Kapan Digunakan?
07 Jul 2025
48 Custom Options di Protobuf
07 Jul 2025
47 Reserved Fields dan Reserved Numbers
07 Jul 2025
23 Modularisasi File Resolver dan Skema
07 Jul 2025
45 Cara Menggunakan `option` di Protobuf
07 Jul 2025

26 Apa Itu Mutation dan Kapan Digunakan?

48 Custom Options di Protobuf

47 Reserved Fields dan Reserved Numbers

23 Modularisasi File Resolver dan Skema
