Napsání základního balíčku banky

Dokončeno

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 -vby 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 -vbyste 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 -vby 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 -vbyste 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.