Bankacılık Sistemi
Coddy'nin GO Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 106 / 107.
Görev
KolayHesapları, işlemleri ve finansal operasyonları yöneten bir Bankacılık Sistemi oluşturalım! Veri bütünlüğünün kritik olduğu sağlam bir sistem oluşturacaksınız: hesap bakiyeleri yalnızca doğrulanmış yöntemler aracılığıyla değişmeli ve kredili mevduat hesabı aşımı veya geçersiz tutarlar gibi hatalar sorunsuz bir şekilde ele alınmalıdır.
Kodunuzu beş dosyaya ayıracaksınız:
account.go:TransactableveDeposit(amount float64) erroryöntemlerine sahip birWithdraw(amount float64) errorarayüzü tanımlayın. Ardından bu arayüzü uygulayan iki hesap türü oluşturun:Export edilmemiş
CheckingAccount,idveholderalanlarına sahip birbalance. Cari hesaplar, bakiyeyi tam olarak sıfıra indiren para çekme işlemlerine izin verir ancak bakiyenin sıfırın altına düşmesine izin vermez.Aynı export edilmemiş alanlara ek olarak bir
SavingsAccountalanına sahip birminBalance. Tasarruf hesapları 100.0 tutarında minimum bakiye korumalıdır: bu eşik değerin altına düşmeye neden olacak para çekme işlemleri başarısız olmalıdır.Her iki hesap türünün de oluşturuculara (
NewCheckingAccountveNewSavingsAccount) ve birBalance() float64getter yöntemine ihtiyacı vardır. Para yatırma işlemlerinde negatif veya sıfır tutarları reddedin. Para çekme işlemlerinde negatif veya sıfır tutarları ve kullanılabilir bakiyeyi aşan tutarları reddedin.transaction.go: Hesap hareketlerini kaydetmek için birTransactionyapısı oluşturun. Her işlemin birType(string: "deposit" veya "withdrawal"),Amount(float64) veAccountID(string) alanı vardır. BirNewTransactionoluşturucusu ve şu biçimi döndüren birString() stringyöntemi ekleyin: tutarın iki ondalık basamağa biçimlendirildiği[Type] $[Amount] on [AccountID].bank.go: Birden çok hesabı yöneten ve işlemleri kaydeden birBankyapısı oluşturun. Hesapları ID'ye göre bir map'te saklayın ve işlemlerden oluşan bir slice tutun. Şunları uygulayın:NewBank() *Bank: boş koleksiyonları başlatırAddAccount(id string, account Transactable): bir hesabı kaydederDeposit(accountID string, amount float64) error: bir hesaba para yatırır ve başarılı olursa işlemi kaydederWithdraw(accountID string, amount float64) error: bir hesaptan para çeker ve başarılı olursa işlemi kaydederTransfer(fromID, toID string, amount float64) error: hesaplar arasında parayı atomik olarak aktarır (para çekme başarılı ancak para yatırma başarısız olursa para çekme işlemini geri alın)GetBalance(accountID string) (float64, error): bir hesabın bakiyesini döndürür
Mevcut olmayan hesaplar için uygun hataları döndürün.
errors.go: Bankacılık işlemleriniz için sentinel hatalar tanımlayın:ErrAccountNotFound: bir hesap ID'si mevcut olmadığındaErrInsufficientFunds: para çekme işlemi kullanılabilir bakiyeyi aştığındaErrInvalidAmount: para yatırma/çekme tutarı sıfır veya negatif olduğundaErrMinBalanceRequired: tasarruf hesabından para çekme işlemi minimum bakiyeyi ihlal edeceğinde
main.go: Bir banka oluşturun ve girdiye göre işlemleri gerçekleştirin.Oluşturulacak hesapların sayısını okuyun. Her hesap için hesap türünü (
checkingveyasavings), ID'yi, hesap sahibinin adını ve başlangıç bakiyesini okuyun. Uygun hesap türünü oluşturun ve bankaya ekleyin.Ardından işlem sayısını okuyun. Her işlem şunlardan biridir:
deposit [accountID] [amount]withdraw [accountID] [amount]transfer [fromID] [toID] [amount]balance [accountID]
Her işlem için sonucu yazdırın: başarılı para yatırma/çekme/aktarma işlemleri için
OK, bakiye sorguları için iki ondalık basamağa biçimlendirilmiş bakiye veya başarısız işlemler için sentinel hata mesajlarınızı kullananError: [message].
Aşağıdaki girdiler sağlanacaktır:
- Hesap sayısı, ardından her hesabın türü, ID'si, sahibi ve başlangıç bakiyesi (her biri 4 satır)
- İşlem sayısı, ardından her işlem (her biri 1 satır)
Örneğin, şu veriler verildiğinde:
2
checking
ACC001
Alice
500.00
savings
ACC002
Bob
1000.00
6
deposit ACC001 200
balance ACC001
withdraw ACC002 950
withdraw ACC001 800
transfer ACC001 ACC002 100
balance ACC002Çıktınız şöyle olmalıdır:
OK
700.00
Error: minimum balance required
Error: insufficient funds
OK
1000.00Ve şu veriler verildiğinde:
1
checking
C100
Charlie
100.00
4
withdraw C100 100
balance C100
deposit C100 -50
withdraw C999 50Çıktınız şöyle olmalıdır:
OK
0.00
Error: invalid amount
Error: account not foundTransactable arayüzünün Bank'ın her iki hesap türüyle de tek tip şekilde çalışmasına nasıl olanak sağladığına dikkat edin; her hesap türü kendi kurallarını uygularken, Transfer yöntemi atomik işlemleri gösterir: işlemin ortasında bir şeyler ters giderse sistem tutarlı kalır!
Kendin dene
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Hesap sayısını oku
scanner.Scan()
numAccounts, _ := strconv.Atoi(scanner.Text())
// Yeni bir banka oluştur
bank := NewBank()
// Hesapları oku ve oluştur
for i := 0; i < numAccounts; i++ {
scanner.Scan()
accountType := scanner.Text()
scanner.Scan()
id := scanner.Text()
scanner.Scan()
holder := scanner.Text()
scanner.Scan()
balance, _ := strconv.ParseFloat(scanner.Text(), 64)
// TODO: accountType'a göre uygun hesap türünü oluştur
// ve bankaya ekle
_ = accountType
_ = id
_ = holder
_ = balance
}
// İşlem sayısını oku
scanner.Scan()
numOps, _ := strconv.Atoi(scanner.Text())
// Her işlemi işle
for i := 0; i < numOps; i++ {
scanner.Scan()
parts := strings.Fields(scanner.Text())
operation := parts[0]
// TODO: Her işlem türünü ele al:
// - "deposit": hesaba para yatır, "OK" veya hata yazdır
// - "withdraw": hesaptan para çek, "OK" veya hata yazdır
// - "transfer": hesaplar arasında transfer yap, "OK" veya hata yazdır
// - "balance": bakiyeyi al ve 2 ondalık basamağa biçimlendirilmiş olarak yazdır
_ = operation
}
}
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