Struktūrinis programavimas
Pamoka 10 / 11 Failai ir klaidų valdymas ~45 min
2 / 4 📖 Teorija

Visa lentyna vienu ypu — JSON į failą

Kaip []Item paversti failo turiniu? Galėtume rašyti po eilutę, bet yra geriau: JSON — tekstinis formatas, kurį supranta ir Go, ir žmogus, ir beveik kiekviena kita kalba.

encoding/json paketas paverčia visą lentyną tekstu vienu kvietimu:

data, err := json.MarshalIndent(items, "", "  ")

O struct lauko gale gali pridėti žymą (tag) — ji nurodo rakto vardą faile:

type Item struct {
    Title string `json:"title"`
    Pages int    `json:"pages"`
}

Failas atrodys taip — atsidaryk ir paskaityk, tai tiesiog tekstas:

[
  {
    "title": "Dune",
    "pages": 412
  }
]

Įrašymui ir skaitymui naudosim aukšto lygio porą — ji pati atidaro IR uždaro failą (1 žingsnio „atidaryk–naudok–uždaryk" sutvarkytas už tave):

err := os.WriteFile("items.json", data, 0o644)   // įrašo visą failą
data, err := os.ReadFile("items.json")           // perskaito visą failą

Liko viena projektavimo detalė — svarbiausia šios pamokos mintis: pačiame pirmame paleidime failo dar NĖRA. Tai ne klaida, o normali situacija, ir ją apdorojam atskirai:

data, err := os.ReadFile(saveFile)
if errors.Is(err, fs.ErrNotExist) {
    return []Item{}, nil // pirmas paleidimas — tiesiog tuščia lentyna
}

errors.Is atskiria „failo nėra" (normalu → tuščias sąrašas) nuo visų kitų bėdų (tikra klaida → grąžinam err). Programa, kuri lūžta per pirmą paleidimą, nes „nerado savo failo" — programa, kurios niekas nenaudos antrą kartą.

Patarimas. Šitas saveItems + loadItems dizainas — ne šiaip pratimas: tai lygiai tas pats saugojimo sluoksnis, kurį naudosi finaliniame projekte. Susidėliok jį gerai dabar — finale jį tiesiog atsineši.