CodeBlanks Logo Icon CodeBlanks

Challenge 4 - Mini app

Write an inventory with map, struct and function.

Challenge: a phone book

You will write a small phone book app combining maps, structs and functions. The Rehber type keeps people in a map by name and offers three methods:

type Kisi struct {
    Ad    string
    Tel   string
}

type Rehber struct{ kisiler map[string]Kisi }

func (r *Rehber) Ekle(k Kisi) error   // error if the name already exists
func (r *Rehber) Bul(ad string) (Kisi, bool)
func (r *Rehber) Liste() []string       // names, alphabetical

Plan

1) Ekle: if r.kisiler == nil, create it with make; check for duplicates with _, exists := r.kisiler[k.Ad] and return fmt.Errorf("%s zaten kayıtlı", k.Ad); otherwise add. 2) Bul: return with comma-ok. 3) Liste: collect the keys into a slice and sort them with slices.Sort.

Practice Phone book app

Write Rehber following the plan. Add Can and Ada, try adding Ada again and print the error; then print r.Liste() and the phone number found with r.Bul("Can").

Starter code

main.go
package main

import (
    "fmt"
    "slices"
)

func main() {
    // buraya yaz
}

Sample solution

main.go
package main

import (
    "fmt"
    "slices"
)

type Kisi struct {
    Ad  string
    Tel string
}

type Rehber struct{ kisiler map[string]Kisi }

func (r *Rehber) Ekle(k Kisi) error {
    if r.kisiler == nil {
        r.kisiler = make(map[string]Kisi)
    }
    if _, exists := r.kisiler[k.Ad]; exists {
        return fmt.Errorf("%s zaten kayıtlı", k.Ad)
    }
    r.kisiler[k.Ad] = k
    return nil
}

func (r *Rehber) Bul(ad string) (Kisi, bool) {
    k, ok := r.kisiler[ad]
    return k, ok
}

func (r *Rehber) Liste() []string {
    adlar := make([]string, 0, len(r.kisiler))
    for ad := range r.kisiler {
        adlar = append(adlar, ad)
    }
    slices.Sort(adlar)
    return adlar
}

func main() {
    var r Rehber
    r.Ekle(Kisi{"Can", "555-0101"})
    r.Ekle(Kisi{"Ada", "555-0199"})
    fmt.Println(r.Ekle(Kisi{"Ada", "555-0000"}))
    fmt.Println(r.Liste())
    if k, ok := r.Bul("Can"); ok {
        fmt.Println(k.Tel)
    }
}

Expected output

Ada zaten kayıtlı
[Ada Can]
555-0101

Questions and answers

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

1 Why can <code>var r Rehber; r.Ekle(...)</code> crash?

  • It doesn't crash
  • The kisiler map is nil and you can't write to a nil map Correct answer
  • Ekle is undefined
  • Rehber must be a pointer

Explanation: Creating the map with make inside Ekle when it is nil (or writing a NewRehber constructor) prevents this error.

2 Initialize the map

Question
if r.kisiler == nil {
    r.kisiler = ____(map[string]Kisi)
}
Answer
if r.kisiler == nil {
    r.kisiler = make(map[string]Kisi)
}

Explanation: make creates a writable map; writing to a nil map would panic.

3 Method and return

Term Meaning
Ekle error
Bul (Kisi, bool)
List []string (sorted)
nil map Initialize with make

All lessons in Beginner