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.
Görev
KolayGeneric 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) Tfonksiyonu oluşturun. Fonksiyon,Ttür parametresi aracılığıyla heminthem defloat64tü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) Tfonksiyonu oluşturun.main.go: Girdiyi okuyun ve generic fonksiyonlarınızı farklı türlerle gösterin.Bir tür göstergesi (
intveyafloat) okuyun, ardından bir adet (count) ve ardından o kadar değer okuyun. Değerleri türe göre ayrıştırın, hemMaxhem deSumfonksiyonları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 (
intveyafloat) - 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): 57Ve ş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.5Aynı 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
}
}
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
1Go OOP Temelleri
Harici DosyalarGo Çalışma Alanı ve ModüllerPaketler ve İçe AktarmalarDışa Aktarılan ve Aktarılmayan İsimlerGo'da OOP'ye GirişSınıf Olarak Struct'larStruct'larda Metot TanımlamaPointer ve Değer AlıcılarStruct BaşlatmaYapıcı FonksiyonlarÖzet - Basit Hesap Makinesi4Arayüzler
Arayüzlere GirişÖrtük UygulamaSözleşme Olarak ArayüzBoş Arayüz (any)Tür OnaylamaTür SeçimiArayüz BileşimiStringer ve Error ArayüzleriÖzet - Şekil Hesaplayıcı7Kapsülleme
Dışa Aktarılan ve Aktarılmayan AlanlarPaket Seviyesinde KapsüllemeGetter ve Setter MetotlarıGo'da Bilgi GizlemeÖzet - Öğrenci Kayıtları10Generics (Go 1.18+)
Generics'e GirişTür ParametreleriTür KısıtlamalarıGeneric Struct'larGeneric Metotlar İçin Geçici ÇözümÖzet - Generic Koleksiyon13Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıAbstract Factory KalıbıObserver KalıbıStrategy Kalıbı2Türler ve Struct'lar: Derinlemesine İnceleme
Temel ve Bileşik TürlerÖzel Tür TanımlamalarıStruct EtiketleriAnonim Struct'larİç İçe Geçmiş Struct'larSıfır Değerler ve VarsayılanlarÖzet - Rehber5Kalıtım Yerine Kompozisyon
Go'da Neden Kalıtım YokStruct Gömme TemelleriMetot YükseltmeBirden Fazla Struct GömmeGömme vs AgregasyonGömülü Metotları GölgelemeÖzet - Çalışan Hiyerarşisi8Hata Yönetimi ve OOP
error ArayüzüÖzel Hata TürleriHata Sarmalama (fmt.Errorf)Sentinel Hatalarerrors.Is() ve errors.As()Panic, Defer ve RecoverÖzet - Dosya Ayrıştırıcı3İşaretçiler ve Bellek
Go'da İşaretçi TemelleriStruct İşaretçileriDeğer ile Geçme ve Referans ile Geçmenew() FonksiyonuGo'da Garbage CollectionÖzet - Linked List Oluşturucu6Go'da Polimorfizm
Interface'ler ile PolimorfizmGo'da Duck TypingInterface Karşılama KurallarıPolimorfik KoleksiyonlarDependency InjectionÖzet - Payment Processor9Eşzamanlılık ve OOP
Goroutine TemelleriKanallar ve İletişimTamponlu ve Tamponsuz KanallarSelect İfadesisync.Mutex ve sync.RWMutexsync.WaitGroupThread-Safe Struct TasarımıÖzet - Worker Pool