Go
Challenge 3 - Error handling
Write a function returning an error and calling code.
Challenge: a safe order
You will apply error handling. The function siparisVer(stok map[string]int, urun string, adet int) error checks three rules:
- if the quantity is below 1,
ErrGecersizAdet - if the product isn't in stock,
ErrUrunYok - if stock is insufficient,
fmt.Errorf("%s için yalnızca %d adet var: %w", urun, n, ErrYetersizStok)
If there is no error it deducts from stock and returns nil.
Plan
1) Define the three sentinel errors with errors.New in a var (...) block. 2) Check the quantity first, then the product's existence (n, ok := stok[urun]), then sufficiency; return early in each case. 3) If all pass, do stok[urun] -= adet and return nil. Order matters: cheap and general checks first.
Exercise Order function
Write the function and the errors following the plan. For stok := map[string]int{"kalem": 3}, place the orders ("kalem", 2), ("kalem", 5) and ("silgi", 1) in turn; print each error (including nil) on its own line, and finally the result of errors.Is(err2, ErrYetersizStok).
Show example solution
package main
import (
"errors"
"fmt"
)
var (
ErrGecersizAdet = errors.New("geçersiz adet")
ErrUrunYok = errors.New("ürün yok")
ErrYetersizStok = errors.New("yetersiz stok")
)
func siparisVer(stok map[string]int, urun string, adet int) error {
if adet < 1 {
return ErrGecersizAdet
}
n, ok := stok[urun]
if !ok {
return ErrUrunYok
}
if adet > n {
return fmt.Errorf("%s için yalnızca %d adet var: %w", urun, n, ErrYetersizStok)
}
stok[urun] -= adet
return nil
}
func main() {
stok := map[string]int{"kalem": 3}
err1 := siparisVer(stok, "kalem", 2)
err2 := siparisVer(stok, "kalem", 5)
err3 := siparisVer(stok, "silgi", 1)
fmt.Println(err1)
fmt.Println(err2)
fmt.Println(err3)
fmt.Println(errors.Is(err2, ErrYetersizStok))
}
Test yourself
-
How does the caller recognize the "insufficient stock" case?
- err.Error() == "yetersiz stok"
- err != nil
- errors.Is(err, ErrYetersizStok)
- err == ErrYetersizStok
Show answer
errors.Is(err, ErrYetersizStok) — Because the error is wrapped with %w, == fails; errors.Is finds ErrYetersizStok in the chain.
-
Existence check
n, ____ := stok[urun]
if !ok {
return ErrUrunYok
}
Show answer
n, ok := stok[urun]
if !ok {
return ErrUrunYok
}
-
Order and result (kalem: 3)
- kalem, 2
- nil, stock 1
- kalem, 0
- ErrGecersizAdet
- silgi, 1
- ErrUrunYok
- kalem, 9
- ErrYetersizStok (wrapped)
Next lesson: Challenge 4 - Mini app