Turlar yig'indisi nima va uni Go da qanday amalga oshirish mumkin?
sobes.tech AI
AIdan javob
Turlar turi (yoki belgilangan birlik, disjoint union) — bu bir nechta oldindan belgilangan variantlardan birini qabul qilishi mumkin bo'lgan ma'lumotlar turi. Haskell yoki Rust kabi tillardagi (enum) kabi to'g'ridan-to'g'ri qo'llab-quvvatlanmaydi, shuning uchun Go'da turli usullar bilan emulyatsiya qilish mumkin:
-
Interfeyslar va turga ishonch (Type Assertion):
Barcha mumkin bo'lgan variantlarni amalga oshiradigan interfeys yarating. Turlar to'plami qiymati bu interfeys bo'ladi, va aniq variantni aniqlash uchun turga ishonch yoki
type switchishlatiladi.package main import "fmt" // Shape - tur to'plamini ifodalovchi interfeys type Shape interface { Area() float64 } // Circle - variantlardan biri type Circle struct { Radius float64 } func (c Circle) Area() float64 { return 3.14 * c.Radius * c.Radius } // Rectangle - boshqa variant type Rectangle struct { Width, Height float64 } func (r Rectangle) Area() float64 { return r.Width * r.Height } func main() { shapes := []Shape{Circle{Radius: 5}, Rectangle{Width: 3, Height: 4}} for _, s := range shapes { // turga switch yordamida aniqlash switch v := s.(type) { case Circle: fmt.Printf("Doira radius %.2f, maydon: %.2f\n", v.Radius, v.Area()) case Rectangle: fmt.Printf("To'rtburchak o'lchamlari %.2f x %.2f, maydon: %.2f\n", v.Width, v.Height, v.Area()) default: fmt.Println("Noma'lum shakl") } } } -
Boolean flag'lar bilan tuzilgan strukturalar (kamdan-kam ishlatiladi):
Struktura barcha mumkin bo'lgan variantlar uchun maydonlarni va qaysi variant faol ekanligini ko'rsatadigan boolean flag'larni o'z ichiga oladi. Bu xavfli va qo'llab-quvvatlash qiyin.
package main import "fmt" type Result struct { Value int // muvaffaqiyatli natija uchun Err error // xato uchun IsValue bool // Value faol ekanligini ko'rsatadigan flag IsErr bool // Err faol ekanligini ko'rsatadigan flag } func Process(input int) Result { if input > 0 { return Result{Value: input * 2, IsValue: true} } return Result{Err: fmt.Errorf("manfiy son: %d", input), IsErr: true} } func main() { res1 := Process(10) if res1.IsValue { fmt.Printf("Natija: %d\n", res1.Value) } else if res1.IsErr { fmt.Printf("Xato: %v\n", res1.Err) } res2 := Process(-5) if res2.IsValue { fmt.Printf("Natija: %d\n", res2.Value) } else if res2.IsErr { fmt.Printf("Xato: %v\n", res2.Err) } } -
Faol bo'lmagan maydonlar uchun null qiymat bilan tuzilgan strukturalar (ko'pincha Optional/Result uchun ishlatiladi):
Struktura barcha variantlar uchun maydonlarni o'z ichiga oladi, lekin faqat biri null bo'ladi. Bu pointerlar yoki aniq "null" qiymatga ega bo'lgan turlar bilan yaxshi ishlaydi.
package main import "fmt" // Option - Optional turidan Some/None emulyatsiyasi type Option struct { Value *int // qiymat bo'lsa null emas } // None null Option yaratadi func None() Option { return Option{} } // Some qiymat bilan Option yaratadi func Some(val int) Option { return Option{Value: &val} } func main() { opt1 := Some(10) if opt1.Value != nil { fmt.Printf("Qiymat: %d\n", *opt1.Value) } else { fmt.Println("Qiymat yo'q") } opt2 := None() if opt2.Value != nil { fmt.Printf("Qiymat: %d\n", *opt2.Value) } else { fmt.Println("Qiymat yo'q") } }
Go'da tur to'plamini emulyatsiya qilishning eng idiomatik va xavfsiz usuli interfeyslar va type switch foydalanishdir. Bu faqat bitta variant mavjudligini ta'minlaydi va u bilan ishlashda tur xavfsizligini ta'minlaydi.