Escreva o pacote principal do banco
Agora que temos o projeto base em execução junto com nosso arquivo de teste, vamos começar a escrever o código que implementa os recursos e requisitos da unidade anterior. Aqui, revisitamos alguns assuntos que discutimos anteriormente, como erros, estruturas e métodos.
Abra o $GOPATH/src/bankcore/bank.go
arquivo, remova a Hello()
função e vamos começar a escrever a lógica central do nosso sistema bancário online.
Criar estruturas para clientes e contas
Vamos começar por criar uma Customer
estrutura onde temos o nome, morada e número de telefone de uma pessoa que quer tornar-se cliente bancário. Além disso, precisamos de uma estrutura para os Account
dados. Como um cliente pode ter mais de uma conta, vamos incorporar as informações do cliente no objeto da conta. Basicamente, vamos criar o que definimos no TestAccount
teste.
As estruturas de que precisamos podem se parecer com o exemplo de código a seguir:
package bank
// Customer ...
type Customer struct {
Name string
Address string
Phone string
}
// Account ...
type Account struct {
Customer
Number int32
Balance float64
}
Quando você executar o go test -v
comando em seu terminal agora, você deve ver que o teste está passando:
=== RUN TestAccount
--- PASS: TestAccount (0.00s)
PASS
ok github.com/msft/bank 0.094s
Este teste está a passar porque implementámos as estruturas para Customer
e Account
. Agora que temos as estruturas, vamos escrever os métodos para adicionar os recursos que precisamos na versão inicial do nosso banco. Estas características incluem depósito, levantamento e transferência de dinheiro.
Implementar o método de depósito
Precisamos começar com um método para permitir adicionar dinheiro à nossa conta. Mas antes de fazermos isso, vamos criar a TestDeposit
bank_test.go
função no arquivo:
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")
}
}
Ao executar go test -v
o , você verá um teste com falha na saída:
# 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]
Para satisfazer o teste anterior, vamos criar um Deposit
método para nossa Account
estrutura que retorna um erro se o valor recebido for igual ou inferior a zero. Caso contrário, basta adicionar o valor recebido ao saldo da conta.
Use o seguinte código para o Deposit
método:
// 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
}
Ao executar go test -v
o , você verá que o teste está passando:
=== RUN TestAccount
--- PASS: TestAccount (0.00s)
=== RUN TestDeposit
--- PASS: TestDeposit (0.00s)
PASS
ok github.com/msft/bank 0.193s
Você também pode escrever um teste que confirma que você recebe um erro quando tenta depositar um valor negativo, como este:
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")
}
}
Ao executar o go test -v
comando, você verá que o teste está passando:
=== 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
Nota
A partir daqui, escreveremos um caso de teste para cada método. Mas você deve escrever tantos testes em seus programas quanto se sentir confortável, para que possa cobrir cenários esperados e inesperados. Por exemplo, neste caso, a lógica de tratamento de erros é testada.
Implementar o método de retirada
Antes de escrevermos a Withdraw
funcionalidade, vamos escrever o teste para ela:
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")
}
}
Quando você executa o go test -v
comando, você deve ver um teste com falha na saída:
# 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]
Vamos implementar a lógica para o Withdraw
método, onde reduzimos o saldo da conta pelo valor que recebemos como parâmetro. Como fizemos antes, precisamos validar que o número que recebemos é maior que zero e que o saldo na conta é suficiente.
Use o seguinte código para o Withdraw
método:
// 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
}
Ao executar o go test -v
comando, você verá que o teste está passando:
=== 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
Implementar o método de instrução
Vamos escrever um método para imprimir o extrato que inclua o nome, o número e o saldo da conta. Mas primeiro, vamos criar a TestStatement
função:
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")
}
}
Ao executar go test -v
o , você verá um teste com falha na saída:
# 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]
Vamos escrever o Statement
método, que deve retornar uma cadeia de caracteres. (Você tem que substituir esse método mais tarde como um desafio.) Use o seguinte código:
// Statement ...
func (a *Account) Statement() string {
return fmt.Sprintf("%v - %v - %v", a.Number, a.Name, a.Balance)
}
Ao executar go test -v
o , você verá que o teste está passando:
=== 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
Vamos passar para a próxima seção e escrever a API da Web que expõe o Statement
método.