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.

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.
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.
// 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.
// 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 mendefinisikan bagaimana elemen tipe bekerja dalam constraint interface.
// 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.
// ~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.
Siap menguasai wawancara Go Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
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.
// 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 menjelaskan bahwa batasan ini ada untuk menjaga sistem tipe tetap dapat dikelola.
// 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.
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.
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 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, dan desain API.
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 Go.
Zero Values dan Type Constraints
Penanganan zero values dalam kode generik memerlukan pemahaman tentang bagaimana Go menginisialisasi variabel dari tipe berparameter.
// 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.
// 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 comparablemembatasi 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
cmpdanslicesmendemonstrasikan pola generik idiomatik - Zero values melalui
var zero Tmenangani data kosong atau hilang dalam fungsi generik - Struktur data generik yang thread-safe menggabungkan generics dengan primitif sync
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Bagikan
Artikel terkait

Go Error Handling di 2026: Pola, Wrapping, dan Pertanyaan Wawancara Teknis
Panduan lengkap tentang error handling di Go: sentinel error, custom error type, errors.Is, errors.As, error wrapping dengan fmt.Errorf %w, serta pertanyaan wawancara teknis yang sering muncul.

Go dan gRPC di 2026: Microservices Berkinerja Tinggi dan Pertanyaan Wawancara
Pembahasan mendalam tentang gRPC dengan Go di 2026. Protocol Buffers, RPC unary dan streaming, interceptor, pola tingkat produksi, serta pertanyaan wawancara umum untuk backend engineer.

Design Pattern Go: Pattern Esensial dan Pertanyaan Wawancara untuk Developer Go
Kuasai design pattern Go: Functional Options, Strategy, Factory, dan Observer. Contoh kode praktis, praktik terbaik yang idiomatis, dan pertanyaan wawancara umum untuk developer Go.