# Go Generics di 2026: Type Parameters, Constraints, dan Pertanyaan Interview > Kuasai Go generics untuk interview teknis dengan materi type parameters, constraints, operator tilde, dan implementasi praktis seperti generic cache. - Published: 2026-07-08 - Updated: 2026-07-08 - Author: SharpSkill - Reading time: 9 min --- Go 1.18 memperkenalkan generics ke bahasa Go pada Maret 2022, dan sejak itu fitur ini terus berkembang melalui Go 1.21, 1.22, dan seterusnya. Artikel ini membahas pertanyaan interview Go generics yang penting untuk tahun 2026, mulai dari type parameters dasar hingga pola constraint tingkat lanjut yang sering ditanyakan oleh hiring manager. > **Apa Itu Go Generics?** > > Go generics memungkinkan penulisan fungsi dan tipe yang dapat bekerja dengan tipe data apapun sambil tetap menjaga keamanan tipe pada saat kompilasi. Berbeda dengan interface yang menggunakan type assertion saat runtime, generics menyelesaikan tipe pada saat kompilasi, memberikan performa yang lebih baik dan deteksi error yang lebih awal. ## Memahami Type Parameters di Go Type parameters merupakan fondasi dari Go generics. Type parameter adalah placeholder untuk tipe yang ditentukan saat fungsi atau tipe generik digunakan. ```go // generic.go // Basic generic function with type parameter T func PrintSlice[T any](items []T) { for _, item := range items { fmt.Println(item) } } // Usage - type inference determines T automatically func main() { PrintSlice([]int{1, 2, 3}) // T is int PrintSlice([]string{"a", "b"}) // T is string } ``` Sintaks kurung siku `[T any]` mendeklarasikan type parameter `T` yang dibatasi oleh `any`. Kompiler Go menyimpulkan tipe konkret dari argumen yang diberikan, sehingga menghilangkan kebutuhan untuk spesifikasi tipe eksplisit dalam sebagian besar kasus. ## Pertanyaan Interview Umum: Apa Perbedaan Antara `any` dan `comparable`? Pewawancara sering bertanya tentang built-in constraints `any` dan `comparable`. Memahami perbedaan keduanya menunjukkan pengetahuan generics yang solid. ```go // constraints.go // any: accepts all types (alias for interface{}) func Process[T any](value T) T { return value } // comparable: only types that support == and != func Contains[T comparable](slice []T, target T) bool { for _, v := range slice { if v == target { // This comparison requires comparable return true } } return false } // This compiles Contains([]int{1, 2, 3}, 2) // This fails: slices are not comparable // Contains([][]int{{1}, {2}}, []int{1}) ``` Constraint `comparable` membatasi type parameters hanya pada tipe yang mendukung operator kesetaraan. Slice, map, dan fungsi dikecualikan karena Go tidak mendefinisikan kesetaraan untuk tipe-tipe tersebut pada level bahasa. ## Membuat Type Constraints Kustom dengan Interface Go menggunakan interface untuk mendefinisikan constraints kustom, memperluas apa yang dapat diterima oleh fungsi generik. [Spesifikasi Go](https://go.dev/ref/spec#Type_constraints) mendefinisikan bagaimana elemen tipe bekerja dalam constraint interface. ```go // number.go // Custom constraint using type union type Number interface { int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 } // Generic function constrained to numeric types func Sum[T Number](values []T) T { var total T for _, v := range values { total += v // + operator works because all Number types support it } return total } func main() { fmt.Println(Sum([]int{1, 2, 3})) // 6 fmt.Println(Sum([]float64{1.5, 2.5})) // 4.0 } ``` Type union dengan `|` menentukan tipe-tipe mana yang memenuhi constraint. Pendekatan ini memberikan kontrol lebih dibandingkan `any` sambil menghindari type assertion saat runtime. ## Pertanyaan Interview: Jelaskan Operator Tilde `~` dalam Constraints Operator tilde `~` dalam constraints mencocokkan baik tipe maupun semua tipe yang memiliki tipe tersebut sebagai underlying type. Pertanyaan ini menguji pemahaman tentang sistem tipe Go. ```go // underlying.go // ~int matches int and any type with int as underlying type type Signed interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 } // Custom type with int as underlying type type UserID int type Temperature int64 func Abs[T Signed](value T) T { if value < 0 { return -value } return value } func main() { var id UserID = -42 var temp Temperature = -10 fmt.Println(Abs(id)) // 42 - works because ~int matches UserID fmt.Println(Abs(temp)) // 10 - works because ~int64 matches Temperature } ``` Tanpa `~`, constraint `int` hanya akan mencocokkan tipe `int` secara eksak, bukan tipe kustom seperti `UserID`. Tilde memperluas constraint untuk menyertakan tipe turunan, membuat kode generik lebih fleksibel. ## Tipe Generik: Struct dan Method Tipe generik tidak hanya terbatas pada fungsi, tetapi juga mencakup struct dan method. Pola ini sering muncul dalam implementasi struktur data. ```go // stack.go // Generic Stack type type Stack[T any] struct { items []T } // Push adds an element to the stack func (s *Stack[T]) Push(item T) { s.items = append(s.items, item) } // Pop removes and returns the top element func (s *Stack[T]) Pop() (T, bool) { if len(s.items) == 0 { var zero T // Zero value for type T return zero, false } index := len(s.items) - 1 item := s.items[index] s.items = s.items[:index] return item, true } func main() { intStack := Stack[int]{} intStack.Push(10) intStack.Push(20) val, ok := intStack.Pop() // val=20, ok=true } ``` Perlu diperhatikan bahwa method pada tipe generik harus mengulangi type parameter dalam kurung siku tetapi tidak dapat memperkenalkan type parameter baru. Receiver `(s *Stack[T])` mengikat method ke instansiasi spesifik dari `Stack`. ## Pertanyaan Interview: Mengapa Method Tidak Bisa Memiliki Type Parameters Sendiri? Go melarang type parameters tambahan pada method, keputusan desain yang mengejutkan developer yang datang dari bahasa seperti Java atau C#. [Proposal Go generics](https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md) menjelaskan bahwa batasan ini ada untuk menjaga sistem tipe tetap dapat dikelola. ```go // This is NOT valid Go code type Container[T any] struct { value T } // ERROR: methods cannot have type parameters // func (c *Container[T]) Transform[U any](fn func(T) U) U { // return fn(c.value) // } // Valid alternative: use a standalone function func Transform[T, U any](c *Container[T], fn func(T) U) U { return fn(c.value) } ``` Solusinya adalah menggunakan fungsi top-level dengan beberapa type parameters alih-alih method. Desain ini menjaga method dispatch tetap sederhana dan menghindari interaksi kompleks antara tipe receiver dan type parameters method. ## Type Inference dan Constraint Inference Type inference Go mengurangi verbositas saat memanggil fungsi generik. Memahami kapan argumen tipe eksplisit diperlukan membantu menulis kode yang lebih bersih. ```go // inference.go func Map[T, R any](input []T, transform func(T) R) []R { result := make([]R, len(input)) for i, v := range input { result[i] = transform(v) } return result } func main() { numbers := []int{1, 2, 3} // Type inference: T=int, R=string inferred from arguments strings := Map(numbers, func(n int) string { return fmt.Sprintf("%d", n) }) // Explicit types sometimes required for complex cases // Map[int, string](numbers, converter) } ``` Type inference bekerja dari argumen fungsi ke type parameters. Ketika kompiler tidak dapat menyimpulkan tipe dari argumen saja, argumen tipe eksplisit dalam kurung siku menyelesaikan ambiguitas. ## Package Constraints: `cmp` dan `slices` di Standard Library Go 1.21 menambahkan package `cmp` dengan constraint `Ordered` dan fungsi perbandingan. Package `slices` mendemonstrasikan kode generik idiomatik di standard library. ```go // stdlib.go import ( "cmp" "slices" ) func main() { numbers := []int{3, 1, 4, 1, 5, 9} // slices.Sort uses cmp.Ordered constraint internally slices.Sort(numbers) // [1, 1, 3, 4, 5, 9] // Binary search on sorted slice index, found := slices.BinarySearch(numbers, 4) // cmp.Compare returns -1, 0, or 1 result := cmp.Compare(3, 5) // -1 // cmp.Or returns first non-zero value value := cmp.Or(0, 0, 42, 100) // 42 } ``` [Dokumentasi standard library](https://pkg.go.dev/cmp) menunjukkan bagaimana package-package ini memanfaatkan generics untuk operasi yang type-safe pada tipe terurut. Familiaritas dengan package-package ini mendemonstrasikan pengetahuan generics praktis di luar pemahaman teoritis. ## Pertanyaan Interview: Implementasi Generic Cache Latihan interview yang umum meminta kandidat untuk mengimplementasikan cache generik yang thread-safe. Ini menguji pengetahuan generics, konkurensi dengan [package sync](/technologies/go/interview-questions/sync-primitives), dan desain API. ```go // cache.go import ( "sync" "time" ) type Cache[K comparable, V any] struct { mu sync.RWMutex items map[K]cacheItem[V] } type cacheItem[V any] struct { value V expiration time.Time } func NewCache[K comparable, V any]() *Cache[K, V] { return &Cache[K, V]{ items: make(map[K]cacheItem[V]), } } func (c *Cache[K, V]) Set(key K, value V, ttl time.Duration) { c.mu.Lock() defer c.mu.Unlock() c.items[key] = cacheItem[V]{ value: value, expiration: time.Now().Add(ttl), } } func (c *Cache[K, V]) Get(key K) (V, bool) { c.mu.RLock() defer c.mu.RUnlock() item, exists := c.items[key] if !exists || time.Now().After(item.expiration) { var zero V return zero, false } return item.value, true } ``` Implementasi ini menggunakan `comparable` untuk key (persyaratan map) dan `any` untuk value. Struct `cacheItem` yang terpisah menunjukkan bagaimana tipe generik dapat bersarang satu sama lain. Thread safety berasal dari `sync.RWMutex`, pola yang dibahas dalam [interview konkurensi](/technologies/go/interview-questions/concurrency-patterns) Go. ## Zero Values dan Type Constraints Penanganan zero values dalam kode generik memerlukan pemahaman tentang bagaimana Go menginisialisasi variabel dari tipe berparameter. ```go // zero.go // Return zero value when slice is empty func First[T any](slice []T) T { if len(slice) == 0 { var zero T // Zero value: 0 for int, "" for string, nil for pointers return zero } return slice[0] } // Alternative: return pointer to avoid ambiguity func FirstOrNil[T any](slice []T) *T { if len(slice) == 0 { return nil } return &slice[0] } ``` Pola `var zero T` membuat zero value untuk tipe `T` apapun. Untuk tipe di mana zero adalah nilai yang valid (seperti `0` untuk integer), varian yang mengembalikan pointer membedakan antara "tidak ditemukan" dan "ditemukan zero." ## Lanjutan: Menggabungkan Beberapa Constraints Fungsi generik yang kompleks mungkin memerlukan tipe untuk memenuhi beberapa constraints. Go menangani ini melalui interface embedding. ```go // combined.go // Constraint requiring both ordering and string conversion type Stringable interface { String() string } type OrderedStringable interface { cmp.Ordered Stringable } // Alternative: use type parameters with multiple constraints inline func PrintSorted[T interface{ cmp.Ordered; fmt.Stringer }](items []T) { slices.Sort(items) for _, item := range items { fmt.Println(item.String()) } } ``` Interface embedding menggabungkan constraints, mengharuskan tipe untuk mengimplementasikan semua interface yang di-embed. Sintaks inline `interface{ A; B }` menyediakan fungsionalitas yang sama tanpa mendeklarasikan tipe constraint bernama. ## Kesimpulan - Type parameters dengan `[T any]` memungkinkan penulisan kode yang dapat digunakan ulang dan type-safe tanpa refleksi runtime - `comparable` membatasi pada tipe yang mendukung `==` dan `!=`, diperlukan untuk map keys - Operator tilde `~` mencocokkan tipe dengan underlying type tertentu, memperluas fleksibilitas constraint - Constraints kustom menggunakan type union (`int | string`) untuk menentukan tipe yang diizinkan secara eksak - Method tidak dapat memiliki type parameters sendiri; gunakan fungsi top-level sebagai alternatif - Package standard library `cmp` dan `slices` mendemonstrasikan pola generik idiomatik - Zero values melalui `var zero T` menangani data kosong atau hilang dalam fungsi generik - Struktur data generik yang thread-safe menggabungkan generics dengan primitif sync --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/id/blog/go/go-generics-type-parameters-constraints-interview-questions