Belajar Golang - Data Types, Struct, Interface, dan Generik
Episode 5 of 19

Belajar Golang - Data Types, Struct, Interface, dan Generik

Episode ini membedah modeling data di Go: struct sebagai model data dengan field tags dan method receiver, interface dengan duck typing idiomatik, serta generik modern dengan type constraints, slice dan map generik, dan reusable algorithms.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Program yang berisi banyak variabel terpisah akan cepat kacau. Di sinilah struct dan interface berperan: struct membentuk model data, interface mendefinisikan kontrak perilaku. Ditambah generik yang stabil sejak Go 1.18, kalian bisa menulis algoritma reusable tanpa kehilangan type safety.

Episode 5 membahas ketiga elemen ini secara mendalam: struct dengan field tags dan method receiver, interface dengan duck typing, serta generik modern dengan constraint dan slice/map generik. Ini perangkat modeling data yang akan kalian pakai di semua episode berikutnya.

Struct sebagai Model Data

Deklarasi dan Field Tags

Struct adalah kumpulan field bernama dengan tipe tertentu. Field tags adalah string metadata di belakang tipe field — tag paling umum dipakai untuk encoding JSON:

Struct dengan JSON tags
package main
 
import (
	"encoding/json"
	"fmt"
)
 
type Pengguna struct {
	Nama string `json:"nama"`
	Umur int    `json:"umur"`
}
 
func main() {
	u := Pengguna{Nama: "Arman", Umur: 30}
	data, _ := json.Marshal(u)
	fmt.Println(string(data))
}

Tag json:"nama" mengontrol nama field saat di-marshal dan di-unmarshal. Opsi omitempty menghilangkan field kosong: json:"umur,omitempty". Konvensi tag yang sama dipakai library lain seperti ORM untuk kolom database. Ada tiga cara membuat instance struct: literal keyed Pengguna{Nama: "Arman"}, literal posisional, dan new. Literal keyed lebih disarankan karena eksplisit.

Method Receiver

Method adalah fungsi dengan receiver — tipe yang menjadi pemilik method. Receiver pointer *Pengguna memungkinkan method mengubah field:

Method dengan receiver pointer
type Pengguna struct {
	Nama string
	Umur int
}
 
func (p *Pengguna) BertambahUmur() {
	p.Umur++
}

Aturan konsisten: jika satu method memakai pointer receiver, seluruh method pada tipe itu sebaiknya memakai pointer receiver. Pemakaian yang campur aduk membingungkan dan memicu error "cannot use value as pointer".

Interface dan Duck Typing

Kontrak yang Dipenuhi Secara Implisit

Interface adalah kumpulan method. Sebuah tipe secara implisit memenuhi interface jika memiliki semua method yang dideklarasikan — tanpa kata kunci implements. Inilah esensi duck typing idiomatik Go: selama berperilaku seperti bebek, ia adalah bebek.

Implementasi fmt.Stringer
package main
 
import "fmt"
 
type Pengguna struct {
	Nama string
	Umur int
}
 
func (p Pengguna) String() string {
	return fmt.Sprintf("%s berumur %d", p.Nama, p.Umur)
}
 
func main() {
	var s fmt.Stringer = Pengguna{Nama: "Arman", Umur: 30}
	fmt.Println(s)
}

Dengan mengimplementasikan String(), tipe Pengguna otomatis memenuhi interface fmt.Stringer dari standard library, dan fmt.Println memakai representasi tersebut.

Empty Interface dan any

Sebelum generik, interface{} dipakai untuk tipe apapun. Sejak Go 1.18, alias resminya adalah any. Hati-hati: any menunda pengecekan tipe ke runtime dan menyerahkannya ke pengguna lewat type assertion:

Type assertion pada any
func cetakNilai(v any) {
	if angka, ok := v.(int); ok {
		fmt.Println("integer:", angka)
	}
}

Generik Modern

Type Parameters dan Constraint

Generik memungkinkan fungsi bekerja dengan banyak tipe tanpa duplikasi. Type parameter ditulis dalam kurung siku, dan constraint membatasi tipe yang diizinkan.

Fungsi generik sederhana
package main
 
import "fmt"
 
func CetakDua[T any](a, b T) {
	fmt.Println(a, b)
}
 
func main() {
	CetakDua(1, 2)
	CetakDua("satu", "dua")
}

Constraint Kustom dan Algoritma Reusable

Paket standar menyediakan constraint comparable untuk tipe yang mendukung ==. Untuk kebutuhan khusus, kalian bisa mendefinisikan constraint sendiri:

Constraint kustom
type Numerik interface {
	~int | ~float64
}
 
func RataRata[T Numerik](data []T) T {
	var total T
	for _, v := range data {
		total += v
	}
	return total / T(len(data))
}

Tanda ~ memperbolehkan tipe alias dengan representasi dasar yang sama. Paket slices dan maps yang stabil sejak Go 1.21 memakai generik untuk operasi umum seperti slices.Sort, slices.Contains, dan maps.Keys — tidak perlu lagi menulis helper sort untuk setiap tipe. Untuk melihat daftar fungsi yang tersedia, jalankan go doc slices dari terminal.

Pola Kombinasi dalam Aplikasi Nyata

Dalam aplikasi nyata, ketiganya bekerja bersama. Contoh repository generik:

Repository generik
package main
 
type Penyimpan[T any] struct {
	items []T
}
 
func (s *Penyimpan[T]) Tambah(item T) {
	s.items = append(s.items, item)
}
 
func (s *Penyimpan[T]) Semua() []T {
	return s.items
}

Pola ini memperlihatkan kekuatan Go: struct membawa state, method receiver mendefinisikan perilaku, dan generik membuatnya reusable untuk tipe apapun. Ini menjadi fondasi pola repository yang akan kalian terapkan saat menghubungkan aplikasi ke database di episode 8.

Penutup

Episode 5 melengkapi perangkat modeling data kalian: struct dengan field tags untuk serialisasi dan method receiver untuk perilaku, interface dengan duck typing implisit dan any, serta generik modern dengan type parameters, constraint kustom, dan paket slices dan maps generik.

Inti yang harus dibawa pulang:

  • Struct adalah model data; field tags mengontrol serialisasi JSON.
  • Receiver pointer memungkinkan method mengubah state.
  • Interface dipenuhi secara implisit lewat kumpulan method.
  • any adalah alias interface{} untuk tipe apapun.
  • Generik memakai type parameters dengan constraint.
  • Paket slices dan maps menyediakan algoritma generik standar.

Di episode 6 selanjutnya kita akan membahas error handling, testing, dan debugging dasar — idiom error handling dengan error, fmt.Errorf, dan errors.Is atau errors.As, unit test dengan package testing, table-driven tests, dan benchmarking dengan go test. Kualitas kode kalian akan terukur, bukan sekadar asumsi.

Belajar Golang - Data Types, Struct, Interface, dan Generik | Belajar Golang