Go / Struct методууд

Struct методууд

Өмнөх хичээлд struct үүсгэж, шинж чанаруудад хандаж сурсан. Энэ хичээлд struct-д method (функц) нэмнэ. Method нь struct-тай холбоотой функц юм — struct-ийн шинж чанаруудыг уншиж, өөрчилж чадна.

Method ашигласнаар кодоо бодит амьдралд ойр байдлаар зохион байгуулах боломжтой. Жишээлбэл, Дансны.Мөнгөоруулах(100) гэж бичихэд кодын утга ойлгомжтой болно.

Анхны method бичих

Method бол receiver гэсэн нэмэлт параметртэй функц юм. Receiver нь функц ямар struct-д харьялагдахыг заана:

go
package main

import "fmt"

type Тэгш өнцөгт struct {
    Өргөн  float64
    Өндөр float64
}

// Тэгш өнцөгт-ийн method — receiver нь (т Тэгшөнцөгт)
func (т Тэгшөнцөгт) Талбай() float64 {
    return т.Өргөн * т.Өндөр
}

func (т Тэгшөнцөгт) Периметр() float64 {
    return 2 * (т.Өргөн + т.Өндөр)
}

func main() {
    өрөө := Тэгшөнцөгт{Өргөн: 6, Өндөр: 4}

    fmt.Printf("Талбай: %.0f м²
", өрөө.Талбай())
    fmt.Printf("Периметр: %.0f м
", өрөө.Периметр())
}

Дэлгэцэнд:

код
Талбай: 24 м²
Периметр: 20 м

func (т Тэгшөнцөгт) Талбай() гэдэг нь "Тэгшөнцөгт-ийн Талбай method, дотор нь т нэрээр хандана" гэсэн утгатай. т.Өргөн гэж struct-ийн шинж чанарт хандана.

Pointer receiver — утга өөрчлөх

Дээрх жишээн дэх receiver нь хуулбар дээр ажиллана. Struct-ийн шинж чанарыг өөрчлөх бол pointer receiver ашиглана:

go
package main

import "fmt"

type Данс struct {
    Эзэн   string
    Үлдэгдэл float64
}

// Pointer receiver — struct-г шууд өөрчилнө
func (д *Данс) Оруулах(дүн float64) {
    д.Үлдэгдэл += дүн
    fmt.Printf("%.0f₮ орлоо. Үлдэгдэл: %.0f₮
", дүн, д.Үлдэгдэл)
}

func (д *Данс) Гаргах(дүн float64) {
    if дүн > д.Үлдэгдэл {
        fmt.Println("Үлдэгдэл хүрэлцэхгүй байна")
        return
    }
    д.Үлдэгдэл -= дүн
    fmt.Printf("%.0f₮ гарлаа. Үлдэгдэл: %.0f₮
", дүн, д.Үлдэгдэл)
}

// Value receiver — зөвхөн уншина, өөрчлөхгүй
func (д Данс) Мэдээлэл() string {
    return fmt.Sprintf("%s-ийн данс: %.0f₮", д.Эзэн, д.Үлдэгдэл)
}

func main() {
    данс := Данс{Эзэн: "Номин", Үлдэгдэл: 50000}

    fmt.Println(данс.Мэдээлэл())
    данс.Оруулах(30000)
    данс.Гаргах(20000)
    данс.Гаргах(100000) // Хүрэлцэхгүй
    fmt.Println(данс.Мэдээлэл())
}

Дэлгэцэнд:

код
Номин-ийн данс: 50000₮
30000₮ орлоо. Үлдэгдэл: 80000₮
20000₮ гарлаа. Үлдэгдэл: 60000₮
Үлдэгдэл хүрэлцэхгүй байна
Номин-ийн данс: 60000₮

*Данс pointer receiver нь д.Үлдэгдэл += дүн хийхэд эх struct-г өөрчилнө. Данс value receiver нь зөвхөн уншихад ашиглана.

String() method — хэвлэх хэлбэрийг тодорхойлох

Go-д String() нэртэй method нь fmt.Println хэрхэн хэвлэхийг тодорхойлно:

go
package main

import "fmt"

type Цаг struct {
    Цаг   int
    Минут int
}

func (ц Цаг) String() string {
    return fmt.Sprintf("%02d:%02d", ц.Цаг, ц.Минут)
}

func main() {
    одоо := Цаг{Цаг: 9, Минут: 5}
    fmt.Println(одоо)      // 09:05 — String() дуудагдана
    fmt.Println(одоо.String()) // 09:05
}

Дэлгэцэнд:

код
09:05
09:05

%02d нь "хоёр оронтой болгон хэвлэ, дутвал 0 нөхөж бич" гэсэн format юм. String() method-г тодорхойлох нь кодыг илүү уншигдахуйц болгодог.

Method chain — дараалан дуудах

Method нь struct-г буцаасан тохиолдолд дараалан дуудаж болно:

go
package main

import "fmt"

type Builder struct {
    гарчиг string
    мөрүүд []string
}

func (б *Builder) Гарчиг(г string) *Builder {
    б.гарчиг = г
    return б
}

func (б *Builder) МөрНэмэх(мөр string) *Builder {
    б.мөрүүд = append(б.мөрүүд, мөр)
    return б
}

func (б *Builder) Хэвлэх() {
    fmt.Println("=== " + б.гарчиг + " ===")
    for _, мөр := range б.мөрүүд {
        fmt.Println(мөр)
    }
}

func main() {
    шинэ Builder{}.
        Гарчиг("Мэдэгдэл").
        МөрНэмэх("Маргааш амралт").
        МөрНэмэх("Бүгд цугларна уу.").
        Хэвлэх()
}

Дэлгэцэнд:

код
=== Мэдэгдэл ===
Маргааш амралт
Бүгд цугларна уу.

Дараагийн хичээлд:

Interface буюу Go-ийн хамгийн хүчирхэг ойлголтуудын нэгийг судална. Interface нь "ямар method-тай байх ёстой" гэсэн гэрээ тодорхойлдог бөгөөд уян хатан, дахин ашиглагдахуйц код бичихийн үндэс юм.