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. Jenerik struct, tür güvenliğini korurken herhangi bir türle çalışan veri yapıları oluşturmanı sağlar. Bu, yığınlar, kuyruklar veya anahtar-değer çiftleri gibi yeniden kullanılabilir kapsayıcılar oluşturmak için idealdir.
Genel bir yapı tanımlamak için tür parametresini yapı adının sonuna 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
}Genel işlevlerin aksine, genel bir yapı örneği oluştururken türü açıkça belirtmelisiniz. Go, türü yalnızca bağlamdan çıkaramaz.
Genel struct'lar birden fazla tür parametresine sahip olabilir; bu da onları çiftler veya eşlemeler gibi yapılar için ideal kılar:
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 bir envanter sistemi oluşturalım! Her türle çalışırken tam tür güvenliğini koruyan yeniden kullanılabilir kapsayıcı yapıları oluşturacaksın.
Kodunu iki dosyaya ayıracaksın:
inventory.go: Genel kapsayıcı yapılarını tanımla.İki alana sahip genel bir struct
Item[T any]oluştur:Name(string) veData(T türünde). Bu, esnek bir türde ilişkili veriye sahip herhangi bir öğeyi temsil eder.Container[T any]dilimini tutan tek birItemsalanına sahip genel bir structItem[T]oluştur. Bu kapsayıcı, aynı veri türündeki birden çok öğeyi depolayabilir.Üç alana sahip kısıtlanmış bir genel struct
PricedItem[T int | float64]oluştur: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 işaretçisini döndüren
NewContainer[T any]() *Container[T]işlevini uygula.Addüzerinde bir*Container[T]yöntemi uygula. Bu yöntem bir ad (string) ve veri (T) almalı, bir Item oluşturmalı ve bunu kapsayıcının Items dilimine eklemelidir.Countüzerinde, kapsayıcıdaki öğe sayısını döndüren birContainer[T]yöntemi uygula.main.go: Genel yapılarını farklı türlerle göster.Bir öğe türü (
string,intveyapriced) oku, ardından bir sayı ve öğe ayrıntılarını oku.stringtürü için: ad ve string verisi çiftlerini oku. BirContainer[string]oluştur, tüm öğeleri ekle, ardından her öğeyi[Name]: [Data]biçiminde ve sonrasında toplam sayıyı yazdır.inttürü için: ad ve tamsayı verisi çiftlerini oku. BirContainer[int]oluştur, tüm öğeleri ekle, ardından her öğeyi[Name]: [Data]biçiminde ve sonrasında toplam sayıyı yazdır.pricedtürü için: ad, miktar ve fiyatı (float olarak) üçlüler hâlinde oku. DoğrudanPricedItem[float64]örnekleri oluştur ve her birini fiyat bir ondalık basamak gösterecek şekilde[Name] x[Quantity] @ [Price]biçiminde yazdır.Sayı satırını şu şekilde yazdır:
Total items: [count]
Aşağıdaki girdiler sağlanacaktır:
- 1. satır: Öğe türü (
string,intveyapriced) - 2. satır: Öğe sayısı (tamsayı)
- Sonraki satırlar: Türe göre öğe ayrıntıları
Örneğin, şu girdi verildiğinde:
string
3
Book
Fiction Novel
Pen
Blue Ink
Notebook
Lined PaperÇıktın şu şekilde olmalıdır:
Book: Fiction Novel
Pen: Blue Ink
Notebook: Lined Paper
Total items: 3Şu girdi verildiğinde:
int
2
Apples
50
Oranges
30Çıktın şu şekilde olmalıdır:
Apples: 50
Oranges: 30
Total items: 2Şu girdi verildiğinde:
priced
2
Widget
10
19.99
Gadget
5
49.50Çıktın şu şekilde olmalıdır:
Widget x10 @ 19.9
Gadget x5 @ 49.5
Total items: 2Aynı Container yapısının hem dizelerle hem de tamsayılarla sorunsuz biçimde çalıştığına, PricedItem yapısının ise fiyatlar için yalnızca sayısal türlerin kullanılabilmesini sağlamak üzere bir kısıtlama kullandığına dikkat et. Bu genel struct'ların örneklerini oluştururken tür parametresini açıkça belirtmelisin.
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 PoolKendi başına pratik yap: Online Go derleyicisi