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:
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:
| Aspek | Method p.JarakAsal() | Fungsi JarakAsalFungsi(p) |
|---|---|---|
| Ruang nama | menempel pada tipe Titik | berbagi ruang nama package |
| Keterbacaan | data dan operasi menyatu | data dan operasi terpisah |
| Interface | bisa memenuhi interface | tidak berperan pada interface |
| Akses receiver | t tersedia otomatis | struct 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:
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:
go run method-demo.goOutput yang Dihasilkan:
5
5
10Mari kita telaah baris demi baris program di atas:
- Baris 8–10 (
type Titik struct): mendeklarasikan struct dengan dua field dalam satu baris —X, Y float64— gaya deklarasi berkelompok yang sah di Go. - Baris 12–14 (
func (t Titik) JarakAsal): mendeklarasikan method dengan receiver(t Titik); badan method membacat.Xdant.Ytanpa parameter tambahan. - Baris 16–18 (
func JarakAsalFungsi): mendeklarasikan fungsi biasa dengan isi identik — struct dikirim sebagai parametertsecara eksplisit. - Baris 21 (
p := Titik{X: 3, Y: 4}): membuat nilaiTitikdengan literal keyed. - Baris 22 (
p.JarakAsal()): memanggil method — receiver diisip, hasilnya jarak titik (3,4) ke titik asal, yaitu 5. - Baris 23 (
JarakAsalFungsi(p)): memanggil fungsi biasa dengan hasil yang sama, membuktikan method hanyalah fungsi dengan receiver. - 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:
package main
import (
"fmt"
"strings"
)
func (s string) Kapital() string {
return strings.ToUpper(s)
}
func main() {
fmt.Println("halo".Kapital())
}go run error-method-external.goOutput yang Dihasilkan:
# 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 #
- Spesifikasi Go: Method declarations — sintaks resmi deklarasi method dan receiver.
- A Tour of Go: Methods — tur interaktif method pada tipe buatan.
- Dokumentasi package math
— fungsi
math.Hypotyang dipakai contoh.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
error-method-external.go
Unduh berkaspackage main
import (
"fmt"
"strings"
)
func (s string) Kapital() string {
return strings.ToUpper(s)
}
func main() {
fmt.Println("halo".Kapital())
}
method-demo.go
Unduh berkaspackage 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())
}