Sobes.tech
Senior

Kas ir tipu summa un kā to īstenot Go?

sobes.tech AI

Atbilde no AI

Veidu tipu summa (vai norādīta apvienība, disjunkta apvienība) — tas ir datu tips, kas var pieņemt vienu no vairākiem iepriekš definētiem variantiem. Atšķirībā no tipu produktu (struktūrām), kur vērtība satur visus laukus vienlaikus, veidu summa satur tikai vienu no iespējamajiem vērtību variantiem.

Go valodā nav tiešas veidu summu atbalsta kā Haskell vai Rust (enum). Veidu summas var imitēt vairākos veidos:

  1. Interfeisi un tipu apstiprinājums (Type Assertion):

    Izveidojiet interfeisu, kas realizēs visas iespējamās variācijas. Veidu summas vērtība būs šis interfeiss, un konkrēto variāciju nosaka, izmantojot tipu apstiprinājumu vai type switch.

    package main
    
    import "fmt"
    
    // Shape - interfeiss, kas pārstāv veidu summu
    type Shape interface {
    	Area() float64
    }
    
    // Circle - viena no variācijām
    type Circle struct {
    	Radius float64
    }
    
    func (c Circle) Area() float64 {
    	return 3.14 * c.Radius * c.Radius
    }
    
    // Rectangle - cita variācija
    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 {
    		// Tipu switch izmantošana variācijas noteikšanai
    		switch v := s.(type) {
    		case Circle:
    			fmt.Printf("Aplis ar rādiusu %.2f, laukums: %.2f\n", v.Radius, v.Area())
    		case Rectangle:
    			fmt.Printf("Rektanguls ar izmēriem %.2f x %.2f, laukums: %.2f\n", v.Width, v.Height, v.Area())
    		default:
    			fmt.Println("Nezināma forma")
    		}
    	}
    }
    
  2. Bultu zīmju struktūras (retāk izmantotas):

    Struktūra satur visus iespējamus laukus un bultu zīmes, kas norāda, kurš variants ir aktīvs. Tas nav droši un grūti uzturēt.

    package main
    
    import "fmt"
    
    type Result struct {
    	Value int  // Veiksmīga rezultāta lauks
    	Err   error // Kļūdas lauks
    
    	IsValue bool // Zīme, kas norāda, vai ir aktīvs Value
    	IsErr   bool // Zīme, kas norāda, vai ir aktīvs Err
    }
    
    func Process(input int) Result {
    	if input > 0 {
    		return Result{Value: input * 2, IsValue: true}
    	}
    	return Result{Err: fmt.Errorf("negatīvs skaitlis: %d", input), IsErr: true}
    }
    
    func main() {
    	res1 := Process(10)
    	if res1.IsValue {
    		fmt.Printf("Rezultāts: %d\n", res1.Value)
    	} else if res1.IsErr {
    		fmt.Printf("Kļūda: %v\n", res1.Err)
    	}
    
    	res2 := Process(-5)
    	if res2.IsValue {
    		fmt.Printf("Rezultāts: %d\n", res2.Value)
    	} else if res2.IsErr {
    		fmt.Printf("Kļūda: %v\n", res2.Err)
    	}
    }
    
  3. Struktūras ar nulles vērtību neaktīviem laukiem (bieži izmanto opcionalus/rezultātus):

    Struktūra satur visus iespējamus laukus, bet tikai viens no tiem būs nulle vērtība. Tas labi darbojas ar norādēm vai tipiem, kuriem ir skaidra "nulles" vērtība.

    package main
    
    import "fmt"
    
    // Option - emulācija ar Some/None no opcionalā tipa
    type Option struct {
    	Value *int // Nav nulle, ja ir vērtība
    }
    
    // None - rada nulle vērtības Option
    func None() Option {
    	return Option{}
    }
    
    // Some - rada Option ar vērtību
    func Some(val int) Option {
    	return Option{Value: &val}
    }
    
    func main() {
    	opt1 := Some(10)
    	if opt1.Value != nil {
    		fmt.Printf("Vērtība ir: %d\n", *opt1.Value)
    	} else {
    		fmt.Println("Vērtība nav")
    	}
    
    	opt2 := None()
    	if opt2.Value != nil {
    		fmt.Printf("Vērtība ir: %d\n", *opt2.Value)
    	} else {
    		fmt.Println("Vērtība nav")
    	}
    }
    

Visdrošākais un idiomātiskākais veids, kā imitēt veidu summas Go valodā, ir izmantot sąsajas un type switch. Tas nodrošina, ka ir tikai viena varianta klātbūtne, un garantē tipa drošību.