Lompati ke konten utama
Modul 5 · Pelajaran 2 dari 522/50 dalam kursus~14 min
Pelajaran modul (2/5)

Metode: nilai vs penerima penunjuk

Metode di Go adalah fungsi dengan penerima: spesial parameter dideklarasikan antara func dan nama metode, yang mengikat metode ke suatu tipe. Tidak ada kelas: metode dapat ditentukan semua tipe bernama yang dideklarasikan dalam paket saat ini.

Sintaksis

Go
type Person struct {
    Name string
}

func (p Person) Greet() string {
    return "ciao " + p.Name
}

p := Person{Name: "Ada"}
fmt.Println(p.Greet())   // "ciao Ada"

Penerima p Person menjadikan Greet sebagai metode Person. Di dalam metode, p adalah variabel seperti yang lainnya.

Penerima nilai vs penerima penunjuk

Go
// VALUE receiver: operates on a COPY of the value
func (p Person) NameUpper() string {
    return strings.ToUpper(p.Name)
}

// POINTER receiver: operates on the original value, can mutate it
func (p *Person) Rename(n string) {
    p.Name = n
}

Dengan penerima penunjuk Anda dapat memodifikasi penerima dan perubahannya terlihat di luar metode. Dengan penerima nilai Anda tidak bisa - Anda akan melakukannya hanya memodifikasi salinan lokal.

Go
p := Person{Name: "Ada"}
p.Rename("Grace")
fmt.Println(p.Name)   // "Grace" — change is visible

Kapan menggunakan penerima penunjuk

Aturan praktis, berdasarkan prioritas:

  1. Anda harus memodifikasi penerima → penerima penunjuk. Wajib.
  2. Strukturnya besar (lusinan bidang, array di dalamnya) → penunjuk penerima untuk menghindari salinan yang mahal.
  3. Konsistensi: jika SETIDAKNYA satu metode pada tipe tersebut memiliki penerima penunjuk, gunakan penerima penunjuk untuk yang lain juga. Sebuah konvensi yang sangat penting untuk antarmuka (Modul 6).
  4. Tipe "nilai" yang kecil dan tidak dapat diubah (waktu.Waktu, bilangan kompleks, kecil struct) → penerima nilai, lebih mudah dibaca.

Metode pada tipe non-struct

Anda dapat mendefinisikan metode pada tipe NAMED apa pun yang dideklarasikan dalam paket Anda:

Go
type Celsius float64

func (c Celsius) ToFahrenheit() float64 {
    return float64(c)*9/5 + 32
}

t := Celsius(20)
fmt.Println(t.ToFahrenheit())  // 68

Anda tidak dapat mendefinisikannya berdasarkan tipe dari paket lain (misalnya int, string): Anda harus pertama-tama buat tipe bernama lokal.

Cobalah

Latihan#go.m5.l2.e1
Upaya: 0Memuat…

Tambahkan metode string Greet() (penerima nilai) ke Person yang mengembalikan 'ciao <Nama>'.

Memuat editor…
Tunjukkan petunjuk

Penerima dalam tanda kurung SEBELUM nama metode.

Solusi tersedia setelah 3 upaya

Latihan#go.m5.l2.e2
Upaya: 0Memuat…

Tambahkan metode Ganti Nama(n string) dengan penerima POINTER yang mengubah p.Nama.

Memuat editor…
Tunjukkan petunjuk

Penerima penunjuk: `(p *Orang)`.

Solusi tersedia setelah 3 upaya

Quiz#go.m5.l2.e3
Siap

Kapan sebaiknya Anda menggunakan penerima penunjuk (p *T)?

Go
func (t ?T) M() { ... }
Pilihan jawaban

Rekap

  • Metode = fungsi dengan penerima: func (r T) Name(...) ... { ... }.
  • Penerima nilai: beroperasi pada salinan; Penerima penunjuk: beroperasi pada aslinya.
  • Go melakukan konversi T ↔ *T secara otomatis di situs panggilan.
  • Penerima penunjuk ketika: mutasi + struct besar + konsistensi dengan metode sejenis lainnya.
  • Jangan pernah mencampur penerima nilai dan penunjuk pada tipe yang sama.
  • Metode menggunakan tipe NAMED dalam paket saat ini (termasuk non-struct).