Go / Interface үндэс

Interface үндэс

Interface бол Go-ийн хамгийн хүчирхэг онцлогуудын нэг. Interface нь "энэ struct ямар method-уудтай байх ёстой" гэсэн гэрээ тодорхойлдог. Хэрэв struct тухайн method-уудыг бүгдийг хэрэгжүүлсэн бол тэр interface-г "хэрэгжүүлсэн" гэж үзнэ.

Go-д interface-г тодорхой зарлан хэрэгжүүлдэггүй — struct-ийн method-ууд таарвал автоматаар хэрэгжүүлсэн гэж тооцогдно. Энэ нь Go-ийн гоёмсог дизайны нэг хэсэг юм.

Анхны interface бичих

go
package main

import (
    "fmt"
    "math"
)

// Дүрс interface — Талбай() method шаарддаг
type Дүрс interface {
    Талбай() float64
}

type Тойрог struct {
    Радиус float64
}

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

// Тойрог interface хэрэгжүүлж байна
func (т Тойрог) Талбай() float64 {
    return math.Pi * т.Радиус * т.Радиус
}

// Тэгшөнцөгт interface хэрэгжүүлж байна
func (т Тэгшөнцөгт) Талбай() float64 {
    return т.Өргөн * т.Өндөр
}

func талбайХэвлэх(д Дүрс) {
    fmt.Printf("Талбай: %.2f
", д.Талбай())
}

func main() {
    тойрог := Тойрог{Радиус: 5}
    тэгш := Тэгшөнцөгт{Өргөн: 4, Өндөр: 6}

    талбайХэвлэх(тойрог) // Тойрог Дүрс interface-г хэрэгжүүлдэг
    талбайХэвлэх(тэгш)   // Тэгшөнцөгт ч мөн адил
}

Дэлгэцэнд:

код
Талбай: 78.54
Талбай: 24.00

талбайХэвлэх функц нь Дүрс interface-г хүлээн авдаг. Талбай() method-той ямар ч struct-г дамжуулж болно. Энэ бол interface-ийн гол давуу тал — нэг функц өөр өөр төрлийн утгуудтай ажиллаж чадна.

Олон method-той interface

Interface нь олон method шаарддаг байж болно:

go
package main

import "fmt"

// Амьтан interface
type Амьтан interface {
    Дуу() string
    Нэр() string
}

type Нохой struct {
    нэр string
}

type Муур struct {
    нэр string
}

func (н Нохой) Дуу() string { return "Хав хав!" }
func (н Нохой) Нэр() string { return н.нэр }

func (м Муур) Дуу() string { return "Миав~" }
func (м Муур) Нэр() string { return м.нэр }

func танилцуул(а Амьтан) {
    fmt.Printf("%s хэлнэ: %s
", а.Нэр(), а.Дуу())
}

func main() {
    нохой := Нохой{нэр: "Бурхан"}
    муур := Муур{нэр: "Цаасан"}

    танилцуул(нохой)
    танилцуул(муур)

    // Slice-д хамт хадгалж болно
    амьтад := []Амьтан{нохой, муур}
    fmt.Println("
Бүх амьтад:")
    for _, а := range амьтад {
        танилцуул(а)
    }
}

Дэлгэцэнд:

код
Бурхан хэлнэ: Хав хав!
Цаасан хэлнэ: Миав~

Бүх амьтад:
Бурхан хэлнэ: Хав хав!
Цаасан хэлнэ: Миав~

[]Амьтан slice нь Амьтан interface-г хэрэгжүүлсэн ямар ч struct-г агуулж чадна. Энэ нь маш уян хатан байдлыг бий болгодог.

Хоосон interface — any

Go-д any (эсвэл interface{}) нь ямар ч утгыг хүлээн авдаг хоосон interface юм:

go
package main

import "fmt"

func юуч(утга any) {
    fmt.Printf("Утга: %v, Төрөл: %T
", утга, утга)
}

func main() {
    юуч(42)
    юуч("Сайн уу")
    юуч(3.14)
    юуч(true)
    юуч([]int{1, 2, 3})
}

Дэлгэцэнд:

код
Утга: 42, Төрөл: int
Утга: Сайн уу, Төрөл: string
Утга: 3.14, Төрөл: float64
Утга: true, Төрөл: bool
Утга: [1 2 3], Төрөл: []int

%T нь утгын төрлийг хэвлэнэ. any ашигласнаар fmt.Println дурын төрлийг хэвлэж чаддаг шалтгаан тодорхой болно — энэ нь ...any параметртэй.

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

Interface-ийн дэвшилтэт хэрэглээг судална — type assertion, type switch болон interface-ийг хэрхэн бодит кодод ашигладаг талаар илүү дэлгэрэнгүй үзнэ.