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)berisim.Harga += rupiah. Sesudahbakso.NaikkanHarga(1000),bakso.Hargajadi berapa:15000atau16000? 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
(m Menu)di antarafuncdan nama method adalah receiver: nilai pemilik method itu. Di dalam method,mdipakai seperti parameter biasa.bakso.Subtotal(3)memanggilnya lewat titik. Go mengisimdenganbakso, danporsidengan3.- Nama method yang diawali huruf besar (
Subtotal) bisa dipanggil dari package lain, sama sepertifmt.Println. - Method cuma boleh dibuat untuk tipe yang kamu definisikan sendiri di package itu.
func (n int) Dobel() intditolak dengancannot define new methods on non-local type int, tapitype Rupiah intlalufunc (r Rupiah) Teks() stringboleh.
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
*Menuartinyamberisi alamatbakso, jadim.Harga += rupiahmengubahbaksoyang asli.- Kamu gak perlu menulis
&bakso. Karenabaksoadalah variabel, Go mengambil alamatnya sendiri:bakso.NaikkanHarga(1000)sama dengan(&bakso).NaikkanHarga(1000). Subtotaltetap value receiver dan membaca harga terbaru: 16000 × 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
- Value receiver untuk method yang mengubah. Compile lolos, gak ada peringatan, tapi perubahannya hilang. Kalau method-nya mengisi field, pakai
*. - Lupa
*di latihan.func (l Lingkaran) Resize(...)membuatl.Radiustetap 7, bukan 14. math.Pipadahal brief minta 3,14.math.Pi * 7 * 7mencetak153.93804002589985, bukan153.86.- Memanggil pointer method di nilai tanpa alamat.
Menu{...}.NaikkanHarga(500)ditolak. Simpan dulu di variabel.
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.