Struct metodlari — Go’da klass yo’qligiga qaramay, struct’ga “xatti-harakat” qo’shish imkonini beradi. Metod — oddiy funksiyaga o’xshaydi, farqi shundaki, u ma’lum bir turga bog’langan (receiver orqali) bo’ladi.
Receiver —
func (o Tur) MetodNomi()yozuvidagi(o Tur)qismi — metodning qaysi turga tegishli ekanini bildiradi. Receiver ikki xil bo’ladi: qiymat (value) yoki ko’rsatkich (pointer), va bu tanlov metodning xatti-harakatiga tubdan ta’sir qiladi.
Diqqat: quyidagi misollarda “to’rtburchak” so’zi ataylab apostrofsiz (Tortburchak) yozilgan — Go kod identifikatorida oddiy tirnoq belgisi (') taqiqlangan, chunki kompilyator uni rune literalining boshlanishi deb talqin qiladi. Shu sabab o’zbekcha so’z va nomlarni Go kodida ishlatganda apostrofdan qochish kerak bo’ladi.
Qiymat receiver bilan metod
package main
import "fmt"
type Tortburchak struct {
Kengligi, Balandligi float64
}
func (t Tortburchak) Yuza() float64 {
return t.Kengligi * t.Balandligi
}
func main() {
t := Tortburchak{Kengligi: 5, Balandligi: 3}
fmt.Println(t.Yuza())
}
15
func (t Tortburchak) Yuza() — Yuza metodi Tortburchak turiga bog’landi. t.Yuza() — oddiy funksiya chaqiruvidan farqli, struct’ning o’ziga “so’rov” kabi o’qiladi.
Qiymat receiver — nusxa ustida ishlaydi
Muhim, ko’pincha kutilmagan xususiyat: qiymat receiver’li metod struct’ning nusxasi ustida ishlaydi — ichkarida qilingan o’zgarish asl obyektga ta’sir qilmaydi:
package main
import "fmt"
type Hisob struct {
Balans int
}
func (h Hisob) QiymatBilanOshir(summa int) {
h.Balans += summa
}
func main() {
h := Hisob{Balans: 100}
h.QiymatBilanOshir(50)
fmt.Println(h.Balans)
}
100
h.Balans — 100ligicha qoldi! QiymatBilanOshir ichidagi h — asl hning nusxasi, uning Balansini o’zgartirish faqat shu nusxaga tegdi va metod tugashi bilan yo’qoldi.
Ko’rsatkich receiver — asl obyektni o’zgartiradi
Struct’ning o’zini o’zgartirish kerak bo’lganda, receiver ko’rsatkich turida e’lon qilinadi:
package main
import "fmt"
type Hisob struct {
Balans int
}
func (h *Hisob) KorsatkichBilanOshir(summa int) {
h.Balans += summa
}
func main() {
h := Hisob{Balans: 100}
h.KorsatkichBilanOshir(50)
fmt.Println(h.Balans)
}
150
func (h *Hisob) ... — receiver endi *Hisob, ya’ni hning manzili. Ichkaridagi h.Balans += summa endi asl obyektning o’zini o’zgartiradi. Diqqat: h.KorsatkichBilanOshir(50) chaqiruvida &h yozish shart emas — Go buni avtomatik bajaradi (ko’rsatkichlar darsida ko’rgan avtomatik dereference’ning aksi).
Qaysi birini tanlash kerak
Amaliy qoida sifatida, agar struct kattaroq bo’lsa yoki metod uning holatini o’zgartirishi kerak bo’lsa — ko’rsatkich receiver ishlatiladi. Farqni jadvalda umumlashtiramiz:
| Receiver turi | Ishlaydi | Qachon ishlatiladi |
|---|---|---|
(t Tur) — qiymat |
nusxa ustida | faqat o’qish, o’zgartirmaydi, kichik struct |
(t *Tur) — ko’rsatkich |
asl obyektda | struct holatini o’zgartirish kerak bo’lsa |
Amaliyotda bir xil turning barcha metodlari odatda bir xil receiver turini ishlatadi — aralashtirish (ba’zisi qiymat, ba’zisi ko’rsatkich) chalkashlik keltirib chiqarishi mumkin, shuning uchun jamoaviy loyihalarda buyoqchilikka rioya qilinadi.