Mis on tüüpide summa ja kuidas seda Go-s rakendada?
sobes.tech AI
Vastus AI-lt
Tüüpide summa (või märgitud unioon, disjunktne unioon) — see on andmetüüp, mis võib võtta üheks mitmest eelnevalt määratletud variandist. Erinevalt tüüpide toodetest (struktuurid), kus väärtus sisaldab kõiki välju korraga, sisaldab tüüpide summa ainult ühte võimalikku väärtust.
Go keeles ei ole otsest tuge tüüpide summade jaoks nagu Haskell või Rust (enum). Tüüpide summasid saab imiteerida mitmel viisil:
-
Liidesed ja tüüpide kinnitamine (Type Assertion):
Looge liides, mis realiseerib kõik võimalikud variandid. Tüüpide summa väärtus esindab seda liidest ning konkreetse variandi määramiseks kasutatakse tüüpide kinnitamist või
type switch.package main import "fmt" // Shape - liides, mis esindab tüüpide summat type Shape interface { Area() float64 } // Circle - üks variant type Circle struct { Radius float64 } func (c Circle) Area() float64 { return 3.14 * c.Radius * c.Radius } // Rectangle - teine 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 { // Tüüpide switch variandi määramiseks switch v := s.(type) { case Circle: fmt.Printf("Ring raadiusega %.2f, pindala: %.2f\n", v.Radius, v.Area()) case Rectangle: fmt.Printf("Ristkülik mõõtmetega %.2f x %.2f, pindala: %.2f\n", v.Width, v.Height, v.Area()) default: fmt.Println("Teadmata kuju") } } } -
Struktuurid koos bult-flagidega (harva kasutatakse):
Struktuur sisaldab kõiki võimalikke välju ja bult-flag-e, mis näitavad, milline variant on aktiivne. See ei ole turvaline ja keeruline hooldada.
package main import "fmt" type Result struct { Value int // Eduka tulemuse väli Err error // Viga väli IsValue bool // Flag, mis näitab, kas aktiivne on Value IsErr bool // Flag, mis näitab, kas aktiivne on Err } func Process(input int) Result { if input > 0 { return Result{Value: input * 2, IsValue: true} } return Result{Err: fmt.Errorf("negatiivne arv: %d", input), IsErr: true} } func main() { res1 := Process(10) if res1.IsValue { fmt.Printf("Tulemus: %d\n", res1.Value) } else if res1.IsErr { fmt.Printf("Viga: %v\n", res1.Err) } res2 := Process(-5) if res2.IsValue { fmt.Printf("Tulemus: %d\n", res2.Value) } else if res2.IsErr { fmt.Printf("Viga: %v\n", res2.Err) } } -
Struktuurid koos nullväärtusega mitteaktiivsetel väljadel (tihti kasutatakse Optional/Result):
Struktuur sisaldab kõiki võimalikke välju, kuid ainult üks neist on nullväärtus. See töötab hästi viitade või tüüpidega, millel on selge "nullväärtus".
package main import "fmt" // Option - emuleerib Some/None valikulise tüübi type Option struct { Value *int // Mitte-null, kui väärtus on olemas } // None loob nullväärtusega Option func None() Option { return Option{} } // Some loob Option väärtusega func Some(val int) Option { return Option{Value: &val} } func main() { opt1 := Some(10) if opt1.Value != nil { fmt.Printf("Väärtus on: %d\n", *opt1.Value) } else { fmt.Println("Väärtus puudub") } opt2 := None() if opt2.Value != nil { fmt.Printf("Väärtus on: %d\n", *opt2.Value) } else { fmt.Println("Väärtus puudub") } }
Kõige idiomaatilisem ja turvalisem viis tüüpide summa imiteerimiseks Go keeles on kasutada liideseid ja type switch. See võimaldab tagada, et on ainult üks variant, ja tagab tüübipõhise turvalisuse töö ajal.