Sobes.tech
Senior

Was ist die Summe der Typen und wie implementiert man sie in Go?

sobes.tech KI

Antwort von AI

Die Summe von Typen (oder etikettierte Vereinigung, disjunkte Vereinigung) ist ein Datentyp, der einen der mehreren vordefinierten Werte annehmen kann. Im Gegensatz zum Produkttyp (Strukturen), bei dem der Wert alle Felder gleichzeitig enthält, enthält die Summe nur einen der möglichen Werte.

In Go gibt es keine direkte Unterstützung für Typ-Summen wie in Sprachen wie Haskell oder Rust (enum). Die Typ-Summe kann auf verschiedene Weisen emuliert werden:

  1. Interfaces und Typ Assertion:

    Erstellen Sie ein Interface, das alle möglichen Varianten implementieren. Der Wert der Typ-Summe ist dieses Interface, und um die konkrete Variante zu bestimmen, wird eine Typ Assertion oder type switch verwendet.

    package main
    
    import "fmt"
    
    // Shape - Interface, das die Summe von Typen repräsentiert
    type Shape interface {
    	Area() float64
    }
    
    // Circle - eine Variante
    type Circle struct {
    	Radius float64
    }
    
    func (c Circle) Area() float64 {
    	return 3.14 * c.Radius * c.Radius
    }
    
    // Rectangle - eine andere Variante
    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 {
    		// Verwendung von type switch zur Bestimmung der Variante
    		switch v := s.(type) {
    		case Circle:
    			fmt.Printf("Kreis mit Radius %.2f, Fläche: %.2f\n", v.Radius, v.Area())
    		case Rectangle:
    			fmt.Printf("Rechteck mit Maßen %.2f x %.2f, Fläche: %.2f\n", v.Width, v.Height, v.Area())
    		default:
    			fmt.Println("Unbekannte Form")
    		}
    	}
    }
    
  2. Strukturen mit booleschen Flags (selten verwendet):

    Die Struktur enthält Felder für alle möglichen Varianten und boolesche Flags, um anzugeben, welche Variante aktiv ist. Unsicher und wartungsintensiv.

    package main
    
    import "fmt"
    
    type Result struct {
    	Value int  // Feld für erfolgreichen Wert
    	Err   error // Feld für Fehler
    
    	IsValue bool // Flag, das angibt, ob Value aktiv ist
    	IsErr   bool // Flag, das angibt, ob Err aktiv ist
    }
    
    func Process(input int) Result {
    	if input > 0 {
    		return Result{Value: input * 2, IsValue: true}
    	}
    	return Result{Err: fmt.Errorf("negative Zahl: %d", input), IsErr: true}
    }
    
    func main() {
    	res1 := Process(10)
    	if res1.IsValue {
    		fmt.Printf("Ergebnis: %d\n", res1.Value)
    	} else if res1.IsErr {
    		fmt.Printf("Fehler: %v\n", res1.Err)
    	}
    
    	res2 := Process(-5)
    	if res2.IsValue {
    		fmt.Printf("Ergebnis: %d\n", res2.Value)
    	} else if res2.IsErr {
    		fmt.Printf("Fehler: %v\n", res2.Err)
    	}
    }
    
  3. Strukturen mit Nullwerten für inaktive Felder (häufig bei Optional/Result verwendet):

    Die Struktur enthält Felder für alle Varianten, aber nur eines ist nicht null. Funktioniert gut mit Zeigern oder Typen, die einen klaren "Null"-Wert haben.

    package main
    
    import "fmt"
    
    // Option - Emulation von Some/None aus dem optionalen Typ
    type Option struct {
    	Value *int // Nicht null, wenn Wert vorhanden
    }
    
    // None erstellt einen Nullwert Option
    func None() Option {
    	return Option{}
    }
    
    // Some erstellt eine Option mit Wert
    func Some(val int) Option {
    	return Option{Value: &val}
    }
    
    func main() {
    	opt1 := Some(10)
    	if opt1.Value != nil {
    		fmt.Printf("Wert: %d\n", *opt1.Value)
    	} else {
    		fmt.Println("Kein Wert")
    	}
    
    	opt2 := None()
    	if opt2.Value != nil {
    		fmt.Printf("Wert: %d\n", *opt2.Value)
    	} else {
    		fmt.Println("Kein Wert")
    	}
    }
    

Die idiomatischste und sichere Methode, um Typ-Summen in Go zu emulieren, ist die Verwendung von Interfaces und type switch. Dies stellt sicher, dass nur eine Variante vorhanden ist, und bietet Typsicherheit bei der Arbeit damit.