Fungsi yang kita tulis pada section sebelumnya berdiri sendiri, terpisah dari data yang diolahnya. Go memungkinkan fungsi menempel pada tipe tertentu lewat receiver, sehingga pemanggilannya memakai notasi titik: p.JarakAsal(). Bentuk inilah yang disebut method — fondasi perilaku pada tipe buatan kita, dan pintu masuk menuju interface pada section berikutnya. Pada chapter ini kita pelajari sintaks deklarasi method, konvensi penamaan receiver, perbedaan method dengan fungsi biasa, serta batasan bahwa method hanya bisa dideklarasikan pada tipe lokal package.

Mendeklarasikan Method #

Method dideklarasikan seperti fungsi biasa, tetapi dengan tambahan parameter receiver yang ditulis dalam kurung sebelum nama method:

go
func (t Titik) JarakAsal() float64 {
	return math.Hypot(t.X, t.Y)
}

Bagian (t Titik) adalah receiver: variabel t bertipe Titik otomatis tersedia di seluruh badan method, seolah method menerima t sebagai parameter pertama. Pemanggilan p.JarakAsal() mengirim p sebagai receiver; kompiler menerjemahkan notasi titik menjadi pemanggilan fungsi dengan receiver sebagai argumen pertamanya.

Konvensi Nama Receiver #

Nama receiver boleh apa pun, tetapi konvensi Go menyarankan nama pendek yang konsisten untuk semua method satu tipe. Jika receiver Titik bernama t, seluruh method Titik sebaiknya memakai t juga — bukan titik pada satu method dan p pada method lain. Nama pendek justru disukai karena setiap pemanggilan method sudah menyebut tipenya (p.JarakAsal()), dan konsistensi memudahkan pembaca mengenali method milik tipe yang sama.

Method vs Fungsi Biasa #

Method dan fungsi biasa sama-sama bisa mengolah struct, tetapi keduanya tidak setara. Tabel berikut merangkum perbedaan yang menentukan pilihan:

AspekMethod p.JarakAsal()Fungsi JarakAsalFungsi(p)
Ruang namamenempel pada tipe Titikberbagi ruang nama package
Keterbacaandata dan operasi menyatudata dan operasi terpisah
Interfacebisa memenuhi interfacetidak berperan pada interface
Akses receivert tersedia otomatisstruct diteruskan sebagai parameter

Fungsi biasa tetap tepat untuk utilitas yang tidak terikat tipe tertentu, misalnya fmt.Println yang melayani segala tipe. Method dipakai ketika operasi secara konseptual milik tipe — menghitung jarak adalah perilaku sebuah Titik, bukan perilaku package secara umum.

Program Utuh #

Berkas method-demo.go membandingkan method dan fungsi biasa secara langsung:

go
package main

import (
	"fmt"
	"math"
)

type Titik struct {
	X, Y float64
}

func (t Titik) JarakAsal() float64 {
	return math.Hypot(t.X, t.Y)
}

func JarakAsalFungsi(t Titik) float64 {
	return math.Hypot(t.X, t.Y)
}

func main() {
	p := Titik{X: 3, Y: 4}
	fmt.Println(p.JarakAsal())
	fmt.Println(JarakAsalFungsi(p))
	fmt.Println(Titik{X: 6, Y: 8}.JarakAsal())
}

Jalankan program dari direktori chapter:

bash
go run method-demo.go

Output yang Dihasilkan:

text
5
5
10

Mari kita telaah baris demi baris program di atas:

  1. Baris 8–10 (type Titik struct): mendeklarasikan struct dengan dua field dalam satu baris — X, Y float64 — gaya deklarasi berkelompok yang sah di Go.
  2. Baris 12–14 (func (t Titik) JarakAsal): mendeklarasikan method dengan receiver (t Titik); badan method membaca t.X dan t.Y tanpa parameter tambahan.
  3. Baris 16–18 (func JarakAsalFungsi): mendeklarasikan fungsi biasa dengan isi identik — struct dikirim sebagai parameter t secara eksplisit.
  4. Baris 21 (p := Titik{X: 3, Y: 4}): membuat nilai Titik dengan literal keyed.
  5. Baris 22 (p.JarakAsal()): memanggil method — receiver diisi p, hasilnya jarak titik (3,4) ke titik asal, yaitu 5.
  6. Baris 23 (JarakAsalFungsi(p)): memanggil fungsi biasa dengan hasil yang sama, membuktikan method hanyalah fungsi dengan receiver.
  7. Baris 24 (Titik{X: 6, Y: 8}.JarakAsal()): memanggil method langsung pada struct literal tanpa variabel perantara.

Method Hanya untuk Tipe Lokal Package #

Go melarang deklarasi method pada tipe yang berasal dari package lain. Berkas error-method-external.go mencoba menambahkan method pada tipe bawaan string:

go
package main

import (
	"fmt"
	"strings"
)

func (s string) Kapital() string {
	return strings.ToUpper(s)
}

func main() {
	fmt.Println("halo".Kapital())
}
bash
go run error-method-external.go

Output yang Dihasilkan:

text
# command-line-arguments
./error-method-external.go:8:9: cannot define new methods on non-local type string
./error-method-external.go:13:21: "halo".Kapital undefined (type untyped string has no field or method Kapital)

Program sengaja gagal dikompilasi — pesan cannot define new methods on non-local type string adalah materinya. Aturan ini menjaga package tetap tertutup: tidak ada pihak luar yang bisa menyuntikkan perilaku baru ke tipe string milik package strings atau runtime. Jika perilaku tambahan memang diperlukan, buat tipe pembungkus lokal, misalnya type Nama string, lalu deklarasikan method pada Nama.

Pemanggilan Method #

Method dipanggil pada variabel, pada struct literal seperti baris terakhir program, dan pada nilai kembalian fungsi. Notasi titik juga berlaku untuk akses bersarang: p.Pengarang.Nama pada chapter Struct diakses dengan pola yang sama. Satu pertanyaan penting belum terjawab: apa yang terjadi bila method perlu mengubah isi struct? Jawabnya bergantung pada jenis receiver — value atau pointer — yang kita bedah pada chapter berikutnya.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

error-method-external.go

Unduh berkas
go
package main

import (
	"fmt"
	"strings"
)

func (s string) Kapital() string {
	return strings.ToUpper(s)
}

func main() {
	fmt.Println("halo".Kapital())
}

method-demo.go

Unduh berkas
go
package main

import (
	"fmt"
	"math"
)

type Titik struct {
	X, Y float64
}

func (t Titik) JarakAsal() float64 {
	return math.Hypot(t.X, t.Y)
}

func JarakAsalFungsi(t Titik) float64 {
	return math.Hypot(t.X, t.Y)
}

func main() {
	p := Titik{X: 3, Y: 4}
	fmt.Println(p.JarakAsal())
	fmt.Println(JarakAsalFungsi(p))
	fmt.Println(Titik{X: 6, Y: 8}.JarakAsal())
}