CodeBlanks Logo Icon CodeBlanks

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.

Practice 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).

Starter code

main.go
package main

import (
    "errors"
    "fmt"
)

func main() {
    // buraya yaz
}

Sample solution

main.go
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))
}

Expected output

<nil>
kalem için yalnızca 1 adet var: yetersiz stok
ürün yok
true

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 How does the caller recognize the "insufficient stock" case?

  • err.Error() == "yetersiz stok"
  • err != nil
  • errors.Is(err, ErrYetersizStok) Correct answer
  • err == ErrYetersizStok

Explanation: Because the error is wrapped with %w, == fails; errors.Is finds ErrYetersizStok in the chain.

2 Existence check

Question
n, ____ := stok[urun]
if !ok {
    return ErrUrunYok
}
Answer
n, ok := stok[urun]
if !ok {
    return ErrUrunYok
}

Explanation: The comma-ok form says whether the product is in the map.

3 Order and result (kalem: 3)

Term Meaning
kalem, 2 nil, stock 1
kalem, 0 ErrGecersizAdet
silgi, 1 ErrUrunYok
kalem, 9 ErrYetersizStok (wrapped)

All lessons in Beginner