Generic Struct'lar
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 70 / 107.
Tıpkı fonksiyonlar gibi, struct'lar da tür parametrelerine sahip olabilir. Bir generic struct, tür güvenliğini korurken herhangi bir türle çalışan veri yapıları oluşturmanıza olanak tanır. Bu; yığınlar, kuyruklar veya anahtar-değer çiftleri gibi yeniden kullanılabilir kapsayıcılar oluşturmak için mükemmeldir.
Genel (generic) bir struct tanımlamak için, tür parametresini struct adından sonra yerleştirin:
type Box[T any] struct {
Value T
}
func main() {
intBox := Box[int]{Value: 42}
strBox := Box[string]{Value: "hello"}
fmt.Println(intBox.Value) // 42
fmt.Println(strBox.Value) // hello
}Generic fonksiyonların aksine, bir generic struct örneği oluştururken türü açıkça belirtmelisiniz. Go, türü tek başına bağlamdan çıkaramaz.
Generic struct'lar birden fazla tip parametresine sahip olabilir, bu da onları çiftler (pairs) veya eşlemeler (maps) gibi yapılar için ideal hale getirir:
type Pair[K, V any] struct {
Key K
Value V
}
p := Pair[string, int]{Key: "age", Value: 25}
fmt.Printf("%s: %d\n", p.Key, p.Value) // age: 25Depolanan türlerin belirli işlemleri desteklemesini sağlamak için kısıtlamalar da uygulayabilirsiniz:
type NumberBox[T int | float64] struct {
Value T
}
nb := NumberBox[float64]{Value: 3.14}Jenerik yapılar, Go'da tip güvenli ve yeniden kullanılabilir veri yapıları oluşturmanın temelini oluşturur. Bir sonraki derste, bu jenerik tipler üzerinde metotların nasıl tanımlanacağını öğreneceksiniz.
Görev
KolayFarklı türdeki öğeleri takip edebilen genel (generic) bir envanter sistemi kuralım! Tam tür güvenliğini korurken her türle çalışan yeniden kullanılabilir konteyner yapıları oluşturacaksınız.
Kodunuzu iki dosya halinde düzenleyeceksiniz:
inventory.go: Genel konteyner yapılarınızı tanımlayın.İki alanı olan genel bir struct
Item[T any]oluşturun:Name(string) veData(T türünde). Bu, esnek bir türdeki ilişkili veriye sahip herhangi bir öğeyi temsil eder.Item[T]dilimini (slice) tutan tek birItemsalanına sahip genel bir structContainer[T any]oluşturun. Bu konteyner, aynı veri türündeki birden fazla öğeyi saklayabilir.Üç alanı olan kısıtlanmış genel bir struct
PricedItem[T int | float64]oluşturun:Name(string),Quantity(int) vePrice(T türünde). Kısıtlama, fiyatların her zaman sayısal olmasını sağlar.Boş bir Container oluşturup ona bir işaretçi (pointer) döndüren bir
NewContainer[T any]() *Container[T]fonksiyonu uygulayın.*Container[T]üzerinde bir isim (string) ve veri (T) alan, bir Item oluşturan ve bunu konteynerin Items dilimine ekleyen birAddmetodu uygulayın.Container[T]üzerinde konteynerdeki öğe sayısını döndüren birCountmetodu uygulayın.main.go: Genel yapılarınızı farklı türlerle gösterin.Bir öğe türü (
string,intveyapriced) okuyun, ardından bir sayı ve ardından öğe detaylarını okuyun.stringtürü için: İsim ve string veri çiftlerini okuyun. BirContainer[string]oluşturun, tüm öğeleri ekleyin, ardından her öğeyi[Name]: [Data]şeklinde ve ardından toplam sayıyı yazdırın.inttürü için: İsim ve tam sayı veri çiftlerini okuyun. BirContainer[int]oluşturun, tüm öğeleri ekleyin, ardından her öğeyi[Name]: [Data]şeklinde ve ardından toplam sayıyı yazdırın.pricedtürü için: İsim, miktar ve fiyat (float olarak) üçlülerini okuyun. DoğrudanPricedItem[float64]örnekleri oluşturun ve her birini fiyat bir ondalık basamak gösterecek şekilde[Name] x[Quantity] @ [Price]olarak yazdırın.Toplam sayı satırını şu şekilde yazdırın:
Total items: [count]
Aşağıdaki girdiler sağlanacaktır:
- Satır 1: Öğe türü (
string,intveyapriced) - Satır 2: Öğe sayısı (tam sayı)
- Sonraki satırlar: Türe göre öğe detayları
Örneğin, şu girdi verildiğinde:
string
3
Book
Fiction Novel
Pen
Blue Ink
Notebook
Lined PaperÇıktınız şöyle olmalıdır:
Book: Fiction Novel
Pen: Blue Ink
Notebook: Lined Paper
Total items: 3Ve şu girdi verildiğinde:
int
2
Apples
50
Oranges
30Çıktınız şöyle olmalıdır:
Apples: 50
Oranges: 30
Total items: 2Ve şu girdi verildiğinde:
priced
2
Widget
10
19.99
Gadget
5
49.50Çıktınız şöyle olmalıdır:
Widget x10 @ 19.9
Gadget x5 @ 49.5
Total items: 2Aynı Container yapısının hem string hem de tam sayılarla nasıl sorunsuz çalıştığına, PricedItem yapısının ise fiyatlar için yalnızca sayısal türlerin kullanılabilmesini sağlamak için nasıl bir kısıtlama kullandığına dikkat edin. Bu genel struct'ların örneklerini oluştururken tür parametresini açıkça belirtmelisiniz.
Kopya kağıdı
Bir generic struct (genel yapı), tip güvenliğini korurken herhangi bir tiple çalışan veri yapıları oluşturmanıza olanak tanır.
Generic bir struct tanımlamak için, tip parametresini struct adından sonra yerleştirin:
type Box[T any] struct {
Value T
}Generic bir struct örneği oluştururken, tipi açıkça belirtmelisiniz (Go bunu çıkarım yoluyla belirleyemez):
intBox := Box[int]{Value: 42}
strBox := Box[string]{Value: "hello"}Generic struct'lar birden fazla tip parametresine sahip olabilir:
type Pair[K, V any] struct {
Key K
Value V
}
p := Pair[string, int]{Key: "age", Value: 25}Depolanan tiplerin belirli işlemleri desteklemesini sağlamak için kısıtlamalar uygulayabilirsiniz:
type NumberBox[T int | float64] struct {
Value T
}
nb := NumberBox[float64]{Value: 3.14}Generic struct'lar, dilimler (slices) dahil olmak üzere tip parametresini kullanan alanlar içerebilir:
type Container[T any] struct {
Items []T
}Generic struct'lar üzerinde metotlar tanımlayabilir ve generic yapıcı (constructor) fonksiyonlar oluşturabilirsiniz:
func NewContainer[T any]() *Container[T] {
return &Container[T]{Items: []T{}}
}
func (c *Container[T]) Add(item T) {
c.Items = append(c.Items, item)
}Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Öğe türünü oku
scanner.Scan()
itemType := scanner.Text()
// Sayısı oku
scanner.Scan()
count, _ := strconv.Atoi(scanner.Text())
switch itemType {
case "string":
// TODO: NewContainer kullanarak bir Container[string] oluşturun
// TODO: 'count' kadar öğe okuyun (her birinin adı bir satırda, verisi sonraki satırda)
// TODO: Her öğeyi konteynere ekleyin
// TODO: Her öğeyi "[Name]: [Data]" şeklinde yazdırın
// TODO: Count metodunu kullanarak "Total items: [count]" yazdırın
case "int":
// TODO: NewContainer kullanarak bir Container[int] oluşturun
// TODO: 'count' kadar öğe okuyun (her birinin adı bir satırda, tam sayı verisi sonraki satırda)
// TODO: Her öğeyi konteynere ekleyin
// TODO: Her öğeyi "[Name]: [Data]" şeklinde yazdırın
// TODO: Count metodunu kullanarak "Total items: [count]" yazdırın
case "priced":
// TODO: PricedItem[float64] örneklerini tutmak için bir slice oluşturun
// TODO: 'count' kadar öğe okuyun (her birinin adı, miktarı ve fiyatı ayrı satırlarda)
// TODO: Her biri için PricedItem[float64] oluşturun ve slice'a ekleyin
// TODO: Her öğeyi, fiyat bir ondalık basamak gösterecek şekilde "[Name] x[Quantity] @ [Price]" olarak yazdırın
// TODO: "Total items: [count]" yazdırın
}
_ = scanner // Girdiyi okumak için scanner kullanın
_ = count // Döngü için count kullanın
}
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