Sistem Perbankan
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan GO di Coddy. Pelajaran 106 dari 107.
Tantangan
MudahMari bangun Sistem Perbankan yang mengelola akun, transaksi, dan operasi keuangan! Kamu akan membuat sistem tangguh yang menjaga integritas data: saldo akun hanya boleh berubah melalui method yang sudah divalidasi, dan error seperti penarikan melebihi saldo atau jumlah yang tidak valid harus ditangani dengan baik.
Kamu akan mengatur kodemu dalam lima file:
account.go: Definisikan interfaceTransactabledengan methodDeposit(amount float64) errordanWithdraw(amount float64) error. Lalu buat dua tipe akun yang mengimplementasikan interface ini:CheckingAccountdengan fieldid,holder, danbalanceyang tidak diekspor. Checking account mengizinkan penarikan yang membuat saldo tepat nol, tetapi tidak boleh kurang dari nol.SavingsAccountdengan field tidak diekspor yang sama, ditambah fieldminBalance. Savings account harus mempertahankan saldo minimum 100.0: penarikan yang membuat saldo turun di bawah batas ini harus gagal.Kedua tipe akun memerlukan konstruktor (
NewCheckingAccountdanNewSavingsAccount) serta method getterBalance() float64. Untuk deposit, tolak jumlah negatif atau nol. Untuk penarikan, tolak jumlah negatif atau nol serta jumlah yang melebihi dana tersedia.transaction.go: Buat structTransactionuntuk mencatat aktivitas akun. Setiap transaksi memilikiType(string: "deposit" atau "withdrawal"),Amount(float64), danAccountID(string). Sertakan konstruktorNewTransactiondan methodString() stringyang mengembalikan format:[Type] $[Amount] on [AccountID]dengan jumlah yang diformat menjadi dua angka desimal.bank.go: Buat structBankyang mengelola beberapa akun dan mencatat transaksi. Simpan akun dalam map berdasarkan ID dan simpan transaksi dalam slice. Implementasikan:NewBank() *Bank: menginisialisasi koleksi kosongAddAccount(id string, account Transactable): mendaftarkan akunDeposit(accountID string, amount float64) error: melakukan deposit ke akun dan mencatat transaksi jika berhasilWithdraw(accountID string, amount float64) error: menarik dana dari akun dan mencatat transaksi jika berhasilTransfer(fromID, toID string, amount float64) error: memindahkan uang antar akun secara atomik (jika penarikan berhasil tetapi deposit gagal, batalkan penarikan)GetBalance(accountID string) (float64, error): mengembalikan saldo akun
Kembalikan error yang sesuai untuk akun yang tidak ada.
errors.go: Definisikan error sentinel untuk operasi perbankanmu:ErrAccountNotFound: ketika ID akun tidak adaErrInsufficientFunds: ketika jumlah penarikan melebihi saldo yang tersediaErrInvalidAmount: ketika jumlah deposit atau penarikan bernilai nol atau negatifErrMinBalanceRequired: ketika penarikan dari savings account akan melanggar saldo minimum
main.go: Buat bank dan proses operasi berdasarkan input.Baca jumlah akun yang akan dibuat. Untuk setiap akun, baca tipe akun (
checkingatausavings), ID, nama pemegang akun, dan saldo awal. Buat tipe akun yang sesuai dan tambahkan ke bank.Lalu baca jumlah operasi. Setiap operasi adalah salah satu dari berikut:
deposit [accountID] [amount]withdraw [accountID] [amount]transfer [fromID] [toID] [amount]balance [accountID]
Untuk setiap operasi, cetak hasilnya:
OKuntuk deposit, penarikan, atau transfer yang berhasil, saldo yang diformat menjadi dua angka desimal untuk permintaan saldo, atauError: [message]untuk kegagalan menggunakan pesan error sentinel milikmu.
Input yang diberikan adalah:
- Jumlah akun, lalu tipe, ID, pemegang akun, dan saldo awal untuk setiap akun (masing-masing 4 baris)
- Jumlah operasi, lalu setiap operasi (masing-masing 1 baris)
Contohnya, jika diberikan:
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 ACC002Outputmu seharusnya:
OK
700.00
Error: minimum balance required
Error: insufficient funds
OK
1000.00Dan jika diberikan:
1
checking
C100
Charlie
100.00
4
withdraw C100 100
balance C100
deposit C100 -50
withdraw C999 50Outputmu seharusnya:
OK
0.00
Error: invalid amount
Error: account not foundPerhatikan bagaimana interface Transactable memungkinkan Bank bekerja dengan kedua tipe akun secara seragam, sementara setiap tipe akun menerapkan aturannya sendiri. Method Transfer menunjukkan operasi atomik. Jika terjadi kesalahan di tengah proses, sistem tetap konsisten!
Coba sendiri
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// Baca jumlah akun
scanner.Scan()
numAccounts, _ := strconv.Atoi(scanner.Text())
// Buat bank baru
bank := NewBank()
// Baca dan buat akun
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: Buat tipe akun yang sesuai berdasarkan accountType
// dan tambahkan ke bank
_ = accountType
_ = id
_ = holder
_ = balance
}
// Baca jumlah operasi
scanner.Scan()
numOps, _ := strconv.Atoi(scanner.Text())
// Proses setiap operasi
for i := 0; i < numOps; i++ {
scanner.Scan()
parts := strings.Fields(scanner.Text())
operation := parts[0]
// TODO: Tangani setiap jenis operasi:
// - "deposit": setorkan dana ke akun, cetak "OK" atau error
// - "withdraw": tarik dana dari akun, cetak "OK" atau error
// - "transfer": transfer dana antar akun, cetak "OK" atau error
// - "balance": ambil dan cetak saldo dengan format 2 angka di belakang koma
_ = operation
}
}
Semua pelajaran di Pemrograman Berorientasi Objek
1Dasar-Dasar OOP di Go
File EksternalWorkspace Go dan modulePaket dan ImporNama yang Diekspor dan Tidak DieksporPengantar OOP di Gostruct sebagai classMendefinisikan method pada structPointer receiver vs value receiverInisialisasi structFungsi KonstruktorUlasan: Kalkulator Sederhana4Interface
Pengenalan InterfaceImplementasi ImplisitInterface sebagai KontrakInterface Kosong (any)Type AssertionType SwitchKomposisi InterfaceInterface Stringer & ErrorUlasan: Kalkulator Bentuk7Enkapsulasi
Field yang Diekspor vs Tidak DieksporEnkapsulasi Tingkat PackageMethod Getter dan SetterPenyembunyian Informasi di GoRingkasan: Data Siswa10Generics (Go 1.18+)
Pengantar GenericsParameter TipeBatasan TipeStruct GenerikCara Alternatif untuk Method GenerikRingkasan Koleksi Generik2Mendalami Tipe dan Struct
Tipe Dasar dan KompositDefinisi Tipe KustomTag StructStruct AnonimStruct BersarangNilai Nol dan Nilai BawaanRangkuman: Buku Kontak5Komposisi daripada Pewarisan
Mengapa Go Tidak Memiliki PewarisanDasar Penyematan StructPromosi methodMenyematkan Beberapa StructPenyematan vs AgregasiMembayangi method yang DisematkanRangkuman: Hierarki Karyawan8Penanganan Error & OOP
Interface errorTipe Error KustomPembungkusan Error (fmt.Errorf)Error Sentinelerrors.Is() dan errors.As()Panic, Defer, dan RecoverRangkuman: Parser File3Pointer dan Memori
Dasar-Dasar Pointer di GoPointer ke StructPass by Value vs ReferenceFungsi new()Garbage Collection di GoRekap: Pembuat Linked List6Polimorfisme di Go
Polimorfisme melalui InterfaceDuck Typing di GoAturan Pemenuhan InterfaceKoleksi PolimorfikInjeksi DependensiRangkuman: Pemroses Pembayaran9Konkruensi & OOP
Dasar-dasar GoroutineChannel & KomunikasiChannel Ber-buffer vs Tanpa BufferPernyataan selectsync.Mutex & sync.RWMutexsync.WaitGroupDesain Struct yang Aman untuk ThreadRingkasan: Worker PoolLatihan sendiri: Compiler Go online