Method — Go

Method di Go Method adalah fungsi yang "terikat" pada sebuah tipe (biasanya struct). Method dideklarasikan dengan menambahkan receiver sebelum nama fungsi…

Method adalah fungsi yang menempel pada sebuah tipe. Bayangin kartu menu di mesin kasir Warung Bakso Mas Bimo: tiap kartu punya tombol sendiri, "hitung subtotal" dan "naikkan harga". Tombolnya milik kartu itu, jadi kamu menekannya lewat kartunya, bakso.Subtotal(3), bukan lewat mesin umum subtotal(bakso, 3).

🧪 Tebakan cepat: method func (m Menu) NaikkanHarga(rupiah int) berisi m.Harga += rupiah. Sesudah bakso.NaikkanHarga(1000), bakso.Harga jadi berapa: 15000 atau 16000? Tebak dulu, jawabannya ada di bagian "Value receiver atau pointer receiver".

Menulis method

package main

import "fmt"

type Menu struct {
	Nama  string
	Harga int
}

func (m Menu) Subtotal(porsi int) int {
	return m.Harga * porsi
}

func main() {
	bakso := Menu{Nama: "Bakso urat", Harga: 15000}
	fmt.Println(bakso.Subtotal(3))
}
$ go run bakso.go
45000

Value receiver atau pointer receiver

Receiver itu argumen juga, jadi ia disalin, sama seperti di lesson Fungsi:

func (m Menu) NaikkanHarga(rupiah int) {
	m.Harga += rupiah
}

bakso.NaikkanHarga(1000)
fmt.Println(bakso.Harga) // 15000

m adalah salinan bakso. Harga salinannya naik, lalu salinan itu dibuang begitu method selesai, jadi bakso.Harga tetap 15000. Itu jawaban tebakannya. Compiler gak memberi peringatan apa pun.

Tambahkan * di depan tipenya, dan receiver-nya jadi pointer receiver:

func (m *Menu) NaikkanHarga(rupiah int) {
	m.Harga += rupiah
}

bakso.NaikkanHarga(1000)
fmt.Println(bakso.Harga)       // 16000
fmt.Println(bakso.Subtotal(3)) // 48000
Method Receiver Kenapa
Subtotal(porsi) (m Menu) cuma membaca, struct-nya kecil
NaikkanHarga(rupiah) (m *Menu) mengubah field
method di struct besar (m *Menu) menghindari menyalin semua field tiap panggilan

Mencampur keduanya seperti di sini sah. Banyak tim Go memilih pointer receiver untuk semua method sebuah tipe begitu satu method butuh pointer, supaya konsisten.

Di latihan: Lingkaran

Latihan memakai pola yang sama dengan struct Lingkaran yang punya field Radius float64. Pakai angka 3.14 dari brief, bukan math.Pi:

Panggilan Rumus Tercetak
l.Luas(), radius 7 3,14 × 7 × 7 153.86
l.Keliling(), radius 7 2 × 3,14 × 7 43.96
l.Resize(2) lalu l.Radius 7 × 2 14

Luas dan Keliling cuma membaca, jadi value receiver (l Lingkaran) cukup. Resize mengubah Radius, jadi wajib pointer receiver (l *Lingkaran), kalau gak, radiusnya tetap 7.

📌 Method set: siapa boleh memanggil apa

Method set adalah daftar method yang dimiliki sebuah tipe. Menu cuma punya method value receiver (Subtotal), sedangkan *Menu punya semuanya (Subtotal dan NaikkanHarga). Pemanggilan lewat variabel tetap jalan karena Go mengambil alamatnya sendiri, tapi nilai yang gak punya alamat gak bisa:

Menu{Nama: "Es teh", Harga: 5000}.NaikkanHarga(500)
./bakso.go:15:36: cannot call pointer method NaikkanHarga on Menu

Aturan ini muncul lagi di lesson Interface: interface yang meminta NaikkanHarga cuma bisa diisi &bakso, bukan bakso.

⚠️ Jebakan yang sering ketemu

TL;DR: Method adalah fungsi dengan receiver: func (m Menu) Subtotal(porsi int) int, dipanggil bakso.Subtotal(3). Receiver disalin seperti argumen, jadi value receiver (m Menu) cuma mengubah salinan dan bakso.Harga tetap 15000. Pointer receiver (m *Menu) mengubah yang asli (16000), dan Go mengambil &bakso sendiri saat dipanggil lewat variabel. Pakai pointer receiver kalau method-nya mengubah field atau struct-nya besar; value receiver untuk yang cuma membaca. Di latihan: Luas 153.86 dan Keliling 43.96 dengan 3,14, lalu Resize dengan (l *Lingkaran) membuat radius 14. *Menu punya semua method, Menu cuma yang value receiver.

Yang akan kamu pelajari