Sobes.tech
Senior

Türlerin toplamı nedir ve Go'da nasıl uygulanır?

sobes.tech yapay zeka

AI'dan gelen yanıt

Türlerin toplamı (veya etiketli birleşim, ayrık birleşim) birkaç önceden tanımlanmış değeri alabilen bir veri türüdür. Haskell veya Rust gibi dillerdeki (enum) gibi doğrudan desteklenmediği için, Go'da tür toplamı birkaç şekilde taklit edilebilir:

  1. Arayüzler ve Tür İddiası (Type Assertion):

    Tüm olası varyantları uygulayan bir arayüz oluşturun. Tür toplamının değeri bu arayüz olacak ve belirli varyantı belirlemek için tür iddiası veya type switch kullanılır.

    package main
    
    import "fmt"
    
    // Shape - toplam türü temsil eden arayüz
    type Shape interface {
    	Area() float64
    }
    
    // Circle - bir varyant
    type Circle struct {
    	Radius float64
    }
    
    func (c Circle) Area() float64 {
    	return 3.14 * c.Radius * c.Radius
    }
    
    // Rectangle - başka bir varyant
    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ür switch kullanarak varyantı belirleme
    		switch v := s.(type) {
    		case Circle:
    			fmt.Printf("Daire yarıçap %.2f, alan: %.2f\n", v.Radius, v.Area())
    		case Rectangle:
    			fmt.Printf("Dikdörtgen ölçüleri %.2f x %.2f, alan: %.2f\n", v.Width, v.Height, v.Area())
    		default:
    			fmt.Println("Bilinmeyen şekil")
    		}
    	}
    }
    
  2. Boolean bayraklar içeren yapılar (nadiren kullanılır):

    Yapı, tüm olası varyantlar için alanlar içerir ve hangi varyantın aktif olduğunu belirten boolean bayraklar içerir. Güvenli değil ve bakım zordur.

    package main
    
    import "fmt"
    
    type Result struct {
    	Value int  // Başarılı sonuç için alan
    	Err   error // Hata için alan
    
    	IsValue bool // Aktif olup olmadığını gösteren bayrak
    	IsErr   bool // Aktif olup olmadığını gösteren bayrak
    }
    
    func Process(input int) Result {
    	if input > 0 {
    		return Result{Value: input * 2, IsValue: true}
    	}
    	return Result{Err: fmt.Errorf("negatif sayı: %d", input), IsErr: true}
    }
    
    func main() {
    	res1 := Process(10)
    	if res1.IsValue {
    		fmt.Printf("Sonuç: %d\n", res1.Value)
    	} else if res1.IsErr {
    		fmt.Printf("Hata: %v\n", res1.Err)
    	}
    
    	res2 := Process(-5)
    	if res2.IsValue {
    		fmt.Printf("Sonuç: %d\n", res2.Value)
    	} else if res2.IsErr {
    		fmt.Printf("Hata: %v\n", res2.Err)
    	}
    }
    
  3. Aktif olmayan alanlar için null değeri içeren yapılar (sıkça Optional/Result için kullanılır):

    Yapı, tüm olası varyantlar için alanlar içerir, ancak yalnızca biri null olmayan değere sahip olur. İşlevseldir ve göstergeçler veya net "null" değeri olan türlerle iyi çalışır.

    package main
    
    import "fmt"
    
    // Option - Opsiyonel türden Some/None emülasyonu
    type Option struct {
    	Value *int // Değer varsa null değil
    }
    
    // None, null Option oluşturur
    func None() Option {
    	return Option{}
    }
    
    // Some, bir değerle Option oluşturur
    func Some(val int) Option {
    	return Option{Value: &val}
    }
    
    func main() {
    	opt1 := Some(10)
    	if opt1.Value != nil {
    		fmt.Printf("Değer: %d\n", *opt1.Value)
    	} else {
    		fmt.Println("Değer yok")
    	}
    
    	opt2 := None()
    	if opt2.Value != nil {
    		fmt.Printf("Değer: %d\n", *opt2.Value)
    	} else {
    		fmt.Println("Değer yok")
    	}
    }
    

Go'da tür toplamını taklit etmenin en idiomatik ve güvenli yolu, arayüzler ve type switch kullanmaktır. Bu, yalnızca bir varyantın mevcut olmasını sağlar ve onunla çalışırken tür güvenliği sağlar.