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 işlevleri yinelemek ya da tür doğrulamalarıyla boş arayüz any kullanmak anlamına geliyordu. Jenerikler, tam tür güvenliğini korurken birden fazla türle çalışan işlevler ve türler yazmanı sağlayarak bu sorunu çözer.
Bir dilimdeki en küçük değeri bulmayı düşün. Jenerikler olmadan, her tür için ayrı işlevler yazman gerekirdi:
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
}Jeneriklerle, köşeli parantezler içinde bir tür parametresi 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], int veya float64 olabilen bir tür parametresi T tanımlar. Artık aynı işlevi kullanarak Min([]int{3, 1, 2}) veya Min([]float64{3.5, 1.2}) çağırabilirsin. Derleyici türleri derleme zamanında denetler; böylece çalışma zamanı ek yükü olmadan güvenlik sağlarsın.
Önümüzdeki derslerde tür parametrelerini, kısıtlamaları ve genel türden yapıları ayrıntılı olarak inceleyeceğiz.
Görev
KolayJeneriklerle hem tam sayı hem de kayan noktalı puanlarla çalışan bir puan analiz aracı oluşturalım! Bir dilimdeki en büyük değeri bulabilen tek bir jenerik işlev oluşturacak ve böylece farklı sayısal türler için yinelenen kod yazma gereksinimini ortadan kaldıracaksın.
Kodunu iki dosyaya yerleştireceksin:
analyzer.go: Jenerik analiz işlevini tanımla.Bir dilimdeki en büyük değeri bulup döndüren
Max[T int | float64](values []T) Tadlı bir jenerik işlev oluştur. Bu işlev, tür parametresiTaracılığıyla heminthem defloat64türleriyle çalışmalıdır.Ayrıca, bir dilimdeki tüm değerlerin toplamını hesaplayıp döndüren
Sum[T int | float64](values []T) Tadlı bir jenerik işlev oluştur.main.go: Girdiyi oku ve jenerik işlevlerini farklı türlerle göster.Bir tür belirtecini (
intveyafloat) oku, ardından bir sayı ve bu sayı kadar değer oku. Değerleri türe göre ayrıştır, uygun türle hemMaxhem deSumişlevlerini çağır ve sonuçları yazdır.Tam sayı girdisi için şunu yazdır:
Max (int): [value] Sum (int): [value]Kayan noktalı sayı girdisi için bir ondalık basamakla yazdır:
Max (float): [value] Sum (float): [value]
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Tür belirteci (
intveyafloat) - 2. satır: Değerlerin sayısı (tam sayı)
- Sonraki satırlar: Her satırda bir değer
Örneğin, şu girdi verildiğinde:
int
4
15
8
23
11Çıktın şöyle olmalıdır:
Max (int): 23
Sum (int): 57Ve şu girdi verildiğinde:
float
3
4.5
9.2
6.8Çıktın şöyle olmalıdır:
Max (float): 9.2
Sum (float): 20.5Aynı jenerik işlevlerin hem tam sayı hem de kayan noktalı verileri nasıl işlediğine dikkat et: [T int | float64] tür parametresi, mantığı yalnızca bir kez yazarken derleyicinin her kullanım için tür güvenli kod üretmesini sağlar.
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ımı oku
countStr, _ := reader.ReadString('\n')
count, _ := strconv.Atoi(strings.TrimSpace(countStr))
if typeStr == "int" {
// Tamsayı 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ı tamsayı dilimiyle çağır
// TODO: Sonuçları "Max (int): [value]" ve "Sum (int): [value]" biçiminde 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 dilimiyle çağır
// TODO: Sonuçları "Max (float): [value]" ve "Sum (float): [value]" biçiminde, virgülden sonra bir basamakla 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 PoolKendi başına pratik yap: Online Go derleyicisi