Napsání základního balíčku banky
Teď, když máme spuštěný základní projekt společně s testovacím souborem, začněme psát kód, který implementuje funkce a požadavky předchozí lekce. Tady se znovu podíváme na několik témat, o kterých jsme mluvili dříve, jako jsou chyby, struktury a metody.
$GOPATH/src/bankcore/bank.go
Otevřete soubor, odeberte Hello()
funkci a začněme psát základní logiku našeho online bankovního systému.
Vytváření struktur pro zákazníky a účty
Začněme vytvořením Customer
struktury, kde máme jméno, adresu a telefonní číslo od osoby, která se chce stát zákazníkem banky. Potřebujeme také strukturu dat Account
. Vzhledem k tomu, že zákazník může mít více účtů, pojďme informace o zákazníci vložit do objektu účtu. V podstatě vytvoříme to, co jsme definovali v TestAccount
testu.
Struktury, které potřebujeme, můžou vypadat jako v následujícím příkladu kódu:
package bank
// Customer ...
type Customer struct {
Name string
Address string
Phone string
}
// Account ...
type Account struct {
Customer
Number int32
Balance float64
}
Když teď spustíte go test -v
příkaz v terminálu, měli byste vidět, že test prochází:
=== RUN TestAccount
--- PASS: TestAccount (0.00s)
PASS
ok github.com/msft/bank 0.094s
Tento test projde, protože jsme implementovali struktury pro Customer
a Account
. Teď, když máme struktury, napište metody pro přidání funkcí, které potřebujeme v počáteční verzi naší banky. Mezi tyto funkce patří vklad, stažení a převod peněz.
Implementace metody vkladu
Musíme začít metodou, která umožňuje přidávání peněz na náš účet. Než to ale uděláme, vytvoříme TestDeposit
funkci v bank_test.go
souboru:
func TestDeposit(t *testing.T) {
account := Account{
Customer: Customer{
Name: "John",
Address: "Los Angeles, California",
Phone: "(213) 555 0147",
},
Number: 1001,
Balance: 0,
}
account.Deposit(10)
if account.Balance != 10 {
t.Error("balance is not being updated after a deposit")
}
}
Při spuštění go test -v
by se ve výstupu měl zobrazit neúspěšný test:
# github.com/msft/bank [github.com/msft/bank.test]
./bank_test.go:32:9: account.Deposit undefined (type Account has no field or method Deposit)
FAIL github.com/msft/bank [build failed]
Abychom splnili předchozí test, vytvoříme metodu Deposit
pro naši Account
strukturu, která vrátí chybu, pokud je přijatá částka rovna nebo nižší než nula. V opačném případě stačí přidat částku přijatou k zůstatku účtu.
Pro metodu Deposit
použijte následující kód:
// Deposit ...
func (a *Account) Deposit(amount float64) error {
if amount <= 0 {
return errors.New("the amount to deposit should be greater than zero")
}
a.Balance += amount
return nil
}
Při spuštění go test -v
byste měli vidět, že test prochází:
=== RUN TestAccount
--- PASS: TestAccount (0.00s)
=== RUN TestDeposit
--- PASS: TestDeposit (0.00s)
PASS
ok github.com/msft/bank 0.193s
Můžete také napsat test, který potvrdí, že se při pokusu o uložení záporné částky zobrazí chyba, například:
func TestDepositInvalid(t *testing.T) {
account := Account{
Customer: Customer{
Name: "John",
Address: "Los Angeles, California",
Phone: "(213) 555 0147",
},
Number: 1001,
Balance: 0,
}
if err := account.Deposit(-10); err == nil {
t.Error("only positive numbers should be allowed to deposit")
}
}
Když spustíte go test -v
příkaz, měli byste vidět, že test prochází:
=== RUN TestAccount
--- PASS: TestAccount (0.00s)
=== RUN TestDeposit
--- PASS: TestDeposit (0.00s)
=== RUN TestDepositInvalid
--- PASS: TestDepositInvalid (0.00s)
PASS
ok github.com/msft/bank 0.197s
Poznámka:
Odsud napíšeme jeden testovací případ pro každou metodu. Měli byste ale do svých programů napsat tolik testů, kolik vám vyhovuje, abyste se mohli zabývat očekávanými i neočekávanými scénáři. V tomto případě se například testuje logika zpracování chyb.
Implementace metody pro stažení
Než začneme Withdraw
psát funkce, zapíšeme pro ni test:
func TestWithdraw(t *testing.T) {
account := Account{
Customer: Customer{
Name: "John",
Address: "Los Angeles, California",
Phone: "(213) 555 0147",
},
Number: 1001,
Balance: 0,
}
account.Deposit(10)
account.Withdraw(10)
if account.Balance != 0 {
t.Error("balance is not being updated after withdraw")
}
}
Při spuštění go test -v
příkazu by se ve výstupu měl zobrazit neúspěšný test:
# github.com/msft/bank [github.com/msft/bank.test]
./bank_test.go:67:9: account.Withdraw undefined (type Account has no field or method Withdraw)
FAIL github.com/msft/bank [build failed]
Pojďme implementovat logiku pro metodu Withdraw
, kdy snížíme zůstatek účtu o částku, kterou obdržíme jako parametr. Stejně jako předtím musíme ověřit, že číslo, které obdržíme, je větší než nula a že zůstatek v účtu stačí.
Pro metodu Withdraw
použijte následující kód:
// Withdraw ...
func (a *Account) Withdraw(amount float64) error {
if amount <= 0 {
return errors.New("the amount to withdraw should be greater than zero")
}
if a.Balance < amount {
return errors.New("the amount to withdraw should be less than the account's balance")
}
a.Balance -= amount
return nil
}
Když spustíte go test -v
příkaz, měli byste vidět, že test prochází:
=== RUN TestAccount
--- PASS: TestAccount (0.00s)
=== RUN TestDeposit
--- PASS: TestDeposit (0.00s)
=== RUN TestDepositInvalid
--- PASS: TestDepositInvalid (0.00s)
=== RUN TestWithdraw
--- PASS: TestWithdraw (0.00s)
PASS
ok github.com/msft/bank 0.250s
Implementace metody příkazu
Pojďme napsat metodu pro tisk příkazu, který obsahuje název účtu, číslo a zůstatek. Nejprve ale vytvoříme TestStatement
funkci:
func TestStatement(t *testing.T) {
account := Account{
Customer: Customer{
Name: "John",
Address: "Los Angeles, California",
Phone: "(213) 555 0147",
},
Number: 1001,
Balance: 0,
}
account.Deposit(100)
statement := account.Statement()
if statement != "1001 - John - 100" {
t.Error("statement doesn't have the proper format")
}
}
Při spuštění go test -v
by se ve výstupu měl zobrazit neúspěšný test:
# github.com/msft/bank [github.com/msft/bank.test]
./bank_test.go:86:22: account.Statement undefined (type Account has no field or method Statement)
FAIL github.com/msft/bank [build failed]
Pojďme napsat metodu Statement
, která by měla vrátit řetězec. (Tuto metodu musíte později přepsat jako výzvu.) Použijte následující kód:
// Statement ...
func (a *Account) Statement() string {
return fmt.Sprintf("%v - %v - %v", a.Number, a.Name, a.Balance)
}
Při spuštění go test -v
byste měli vidět, že test prochází:
=== RUN TestAccount
--- PASS: TestAccount (0.00s)
=== RUN TestDeposit
--- PASS: TestDeposit (0.00s)
=== RUN TestDepositInvalid
--- PASS: TestDepositInvalid (0.00s)
=== RUN TestWithdraw
--- PASS: TestWithdraw (0.00s)
=== RUN TestStatement
--- PASS: TestStatement (0.00s)
PASS
ok github.com/msft/bank 0.328s
Pojďme přejít k další části a napsat webové rozhraní API, které metodu Statement
zveřejňuje.