From 809a8faf67ec9b10c7f7f11add1f8b70002c4b3c Mon Sep 17 00:00:00 2001 From: Drew Bednar Date: Wed, 19 Jun 2024 09:39:24 -0400 Subject: [PATCH] Finished with pointers --- learn_go_with_tests/pointers_errors/README.md | 19 ++++++++++ learn_go_with_tests/pointers_errors/wallet.go | 8 ++++- .../pointers_errors/wallet_test.go | 36 ++++++++++++++++--- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/learn_go_with_tests/pointers_errors/README.md b/learn_go_with_tests/pointers_errors/README.md index 4496445..37f61c9 100644 --- a/learn_go_with_tests/pointers_errors/README.md +++ b/learn_go_with_tests/pointers_errors/README.md @@ -2,3 +2,22 @@ https://quii.gitbook.io/learn-go-with-tests/go-fundamentals/pointers-and-errors +## Handle Errors Gracefully + +A must read: + +https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully + + +The author has a package https://pkg.go.dev/github.com/pkg/errors that you can use to implement the error handling pattern he outlines in the article. + +## Use errcheck + +You can use this static analysis tool to check if you have +potentially not handled an error case in your code + + +``` +go install github.com/kisielk/errcheck@latest +errcheck +``` \ No newline at end of file diff --git a/learn_go_with_tests/pointers_errors/wallet.go b/learn_go_with_tests/pointers_errors/wallet.go index d71514f..889ff51 100644 --- a/learn_go_with_tests/pointers_errors/wallet.go +++ b/learn_go_with_tests/pointers_errors/wallet.go @@ -5,10 +5,16 @@ import ( "fmt" ) + +// The var keyword allows us to define values global to the package. +var ErrInsufficientFunds = errors.New("cannot withdraw, insufficient funds") + type Stringer interface { String() string } +errors.Wrap() + // creating a new type from an existing on // The idea being it could be more descriptive // but also you can declare methods on them @@ -46,7 +52,7 @@ func (w *Wallet) Balance() Bitcoin { func (w *Wallet) Withdraw(amount Bitcoin) error { if amount > w.balance { - return errors.New("Withdraw operation failed. Insufficient funds") + return ErrInsufficientFunds } w.balance -= amount return nil diff --git a/learn_go_with_tests/pointers_errors/wallet_test.go b/learn_go_with_tests/pointers_errors/wallet_test.go index 08ede38..5e59082 100644 --- a/learn_go_with_tests/pointers_errors/wallet_test.go +++ b/learn_go_with_tests/pointers_errors/wallet_test.go @@ -4,6 +4,13 @@ import ( "testing" ) +func assertNoError(t testing.TB, got error) { + t.Helper() + if got != nil { + t.Fatal("got an error but didn't want one") + } +} + func TestWallet(t *testing.T) { assertBalance := func(t *testing.T, wallet Wallet, want Bitcoin) { @@ -15,6 +22,23 @@ func TestWallet(t *testing.T) { } } + assertError := func(t testing.TB, got, want error) { + t.Helper() + if got == nil { + // Fata; will stop the test if called. We do this because we + // don't want to make any more assertions, otherwise we would try + // to access a nil pointer and hit a panic + t.Fatal("wanted error but didn't get one") + } + // cast error to string and compare + // if got.Error() != want { + // t.Errorf("got %q, want %q", got, want) + // } + if got != want { + t.Errorf("got %q, want %q", got, want) + } + } + t.Run("deposit", func(t *testing.T) { wallet := Wallet{} @@ -26,8 +50,13 @@ func TestWallet(t *testing.T) { t.Run("withdraw", func(t *testing.T) { wallet := Wallet{balance: Bitcoin(20)} - wallet.Withdraw(Bitcoin(10)) + // This was found by using + // go install github.com/kisielk/errcheck@latest + // and using `errcheck .` on our code. Could make + // a great pre-commit hook. + err := wallet.Withdraw(Bitcoin(10)) + assertNoError(t, err) assertBalance(t, wallet, Bitcoin(10)) }) @@ -38,10 +67,7 @@ func TestWallet(t *testing.T) { err := wallet.Withdraw(Bitcoin(100)) assertBalance(t, wallet, startingBalance) - - if err == nil { - t.Error("Wanted an error but didn't get one") - } + assertError(t, err, ErrInsufficientFunds) }) }