Wallet
struct which lets us deposit Bitcoin
../wallet_test.go:7:12: undefined: Wallet
Wallet
is so let's tell it.wallet_test.go:15: got 0 want 10
balance
field in the struct using the "receiver" variable.wallet_test.go:15: got 0 want 10
func (w Wallet) Deposit(amount int)
the w
is a copy of whatever we called the method from.&myVal
.&
character at the beginning of the symbol.*Wallet
rather than Wallet
which you can read as "a pointer to a wallet".(*w)
is absolutely valid. However, the makers of Go deemed this notation cumbersome, so the language permits us to write w.balance
, without an explicit dereference. These pointers to structs even have their own name: struct pointers and they are automatically dereferenced.Balance
to use a pointer receiver as taking a copy of the balance is fine. However, by convention you should keep your method receiver types the same for consistency.int
because they're a good type for counting things!struct
for this. int
is fine in terms of the way it works but it's not descriptive.type MyName OriginalType
Bitcoin
you just use the syntax Bitcoin(999)
.fmt
package and lets you define how your type is printed when used with the %s
format string in prints.String()
instead.wallet_test.go:18: got 10 BTC want 20 BTC
Withdraw
function.Deposit()
./wallet_test.go:26:9: wallet.Withdraw undefined (type Wallet has no field or method Withdraw)
wallet_test.go:33: got 20 BTC want 10 BTC
Withdraw
more than is left in the account? For now, our requirement is to assume there is not an overdraft facility.Withdraw
?err
for the caller to check and act on.Withdraw
to return an error if you try to take out more than you have and the balance should stay the same.nil
.nil
is synonymous with null
from other programming languages. Errors can be nil
because the return type of Withdraw
will be error
, which is an interface. If you see a function that takes arguments or returns values that are interfaces, they can be nillable.null
if you try to access a value that is nil
it will throw a runtime panic. This is bad! You should make sure that you check for nils../wallet_test.go:31:25: wallet.Withdraw(Bitcoin(100)) used as value
Withdraw
was just to call it, it will never return a value. To make this compile we will need to change it so it has a return type.Withdraw
method to return error
and for now we have to return something so let's just return nil
.errors
into your code.errors.New
creates a new error
with a message of your choosing.string
to compare against.t.Fatal
which will stop the test if it is called. This is because we don't want to make any more assertions on the error returned if there isn't one around. Without this the test would carry on to the next step and panic because of a nil pointer.wallet_test.go:61: got err 'oh no' want 'cannot withdraw, insufficient funds'
Withdraw
code.var
keyword allows us to define values global to the package.Withdraw
function looks very clear.ErrInsufficientFunds
and act accordingly.errcheck
, one of many linters available for Go.go install github.com/kisielk/[email protected]
errcheck .
wallet_test.go:17:18: wallet.Withdraw(Bitcoin(10))
Withdraw
is successful that an error is not returned.