Menu
Coddy logo textTech

Generics'e Giriş

Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 67 / 107.

Go 1.18'den önce, farklı türler için yeniden kullanılabilir kod yazmak, ya fonksiyonları çoğaltmak ya da tür onaylamaları (type assertions) ile boş arayüz any kullanmak anlamına geliyordu. Generic'ler, tam tür güvenliğini korurken birden fazla türle çalışan fonksiyonlar ve türler yazmanıza olanak tanıyarak bu sorunu çözer.

Bir slice içindeki en küçük değeri bulmayı düşünün. Generic'ler olmadan, her tür için ayrı fonksiyonlara ihtiyacınız olurdu:

func MinInt(values []int) int {
    min := values[0]
    for _, v := range values {
        if v < min {
            min = v
        }
    }
    return min
}

func MinFloat64(values []float64) float64 {
    min := values[0]
    for _, v := range values {
        if v < min {
            min = v
        }
    }
    return min
}

Generic'ler ile, köşeli parantezler içindeki bir tip parametresini kullanarak mantığı bir kez yazarsınız:

func Min[T int | float64](values []T) T {
    min := values[0]
    for _, v := range values {
        if v < min {
            min = v
        }
    }
    return min
}

[T int | float64], hem int hem de float64 olabilen bir T tip parametresi bildirir. Artık aynı fonksiyonla Min([]int{3, 1, 2}) veya Min([]float64{3.5, 1.2}) çağırabilirsiniz. Derleyici, tipleri derleme zamanında kontrol eder, böylece çalışma zamanı yükü olmadan güvenlik elde edersiniz.

Gelecek derslerde tür parametrelerini, kısıtlamaları ve generic struct'ları ayrıntılı olarak inceleyeceğiz.

challenge icon

Görev

Kolay

Generic yapıları kullanarak hem tam sayı hem de ondalıklı sayı puanlarıyla çalışan bir puan analizörü oluşturalım! Farklı sayısal türler için mükemmel bir şekilde yinelenen kod ihtiyacını ortadan kaldıran, bir dilimdeki (slice) maksimum değeri bulabilen tek bir generic fonksiyon oluşturacaksınız.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • analyzer.go: Generic analiz fonksiyonunuzu tanımlayın.

    Bir dilimdeki maksimum değeri bulan ve döndüren generic bir Max[T int | float64](values []T) T fonksiyonu oluşturun. Fonksiyon, T tür parametresi aracılığıyla hem int hem de float64 türleriyle çalışmalıdır.

    Ayrıca bir dilimdeki tüm değerlerin toplamını hesaplayan ve döndüren generic bir Sum[T int | float64](values []T) T fonksiyonu oluşturun.

  • main.go: Girdiyi okuyun ve generic fonksiyonlarınızı farklı türlerle gösterin.

    Bir tür göstergesi (int veya float) okuyun, ardından bir adet (count) ve ardından o kadar değer okuyun. Değerleri türe göre ayrıştırın, hem Max hem de Sum fonksiyonlarını uygun türle çağırın ve sonuçları yazdırın.

    Tam sayı girdisi için şunu yazdırın:

    Max (int): [value]
    Sum (int): [value]

    Ondalıklı sayı girdisi için bir ondalık basamakla yazdırın:

    Max (float): [value]
    Sum (float): [value]

Aşağıdaki girdiler sağlanacaktır:

  • Satır 1: Tür göstergesi (int veya float)
  • Satır 2: Değerlerin adedi (tam sayı)
  • Sonraki satırlar: Her satırda bir değer

Örneğin, şu verildiğinde:

int
4
15
8
23
11

Çıktınız şöyle olmalıdır:

Max (int): 23
Sum (int): 57

Ve şu verildiğinde:

float
3
4.5
9.2
6.8

Çıktınız şöyle olmalıdır:

Max (float): 9.2
Sum (float): 20.5

Aynı generic fonksiyonların hem tam sayı hem de ondalıklı sayı verilerini nasıl işlediğine dikkat edin; [T int | float64] tür parametresi, siz mantığı yalnızca bir kez yazarken derleyicinin her kullanım için tür açısından güvenli kod oluşturmasına olanak tanır.

Kendin dene

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Tür göstergesini oku
	typeStr, _ := reader.ReadString('\n')
	typeStr = strings.TrimSpace(typeStr)

	// Sayısı oku
	countStr, _ := reader.ReadString('\n')
	count, _ := strconv.Atoi(strings.TrimSpace(countStr))

	if typeStr == "int" {
		// Tam sayı değerlerini oku
		values := make([]int, count)
		for i := 0; i < count; i++ {
			line, _ := reader.ReadString('\n')
			values[i], _ = strconv.Atoi(strings.TrimSpace(line))
		}

		// TODO: Max ve Sum fonksiyonlarını integer slice ile çağır
		// TODO: Sonuçları "Max (int): [value]" ve "Sum (int): [value]" formatında yazdır

	} else if typeStr == "float" {
		// Ondalıklı sayı değerlerini oku
		values := make([]float64, count)
		for i := 0; i < count; i++ {
			line, _ := reader.ReadString('\n')
			values[i], _ = strconv.ParseFloat(strings.TrimSpace(line), 64)
		}

		// TODO: Max ve Sum fonksiyonlarını float64 slice ile çağır
		// TODO: Sonuçları virgülden sonra bir basamak olacak şekilde "Max (float): [value]" ve "Sum (float): [value]" formatında yazdır
	}
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler