// Chapter 35 example: loading and saving a JSON file, with no server. Each run // adds one note. It reads and writes notes.json in the folder you run it from. // Run with: go run exercises/35/04-notes-file.go package main import ( "encoding/json" "errors" "fmt" "os" ) const notesFile = "notes.json" type note struct { Text string } // loadNotes reads the file. A file that does not exist yet means no notes, which // is normal on the first run. Any other problem is an error. func loadNotes() ([]note, error) { data, err := os.ReadFile(notesFile) if errors.Is(err, os.ErrNotExist) { return []note{}, nil } if err != nil { return nil, err } var loaded []note err = json.Unmarshal(data, &loaded) if err != nil { return nil, fmt.Errorf("%s is not valid: %v", notesFile, err) } return loaded, nil } // saveNotes writes a temporary file, then renames it over the real one. func saveNotes(list []note) error { data, err := json.MarshalIndent(list, "", " ") if err != nil { return err } temporary := notesFile + ".tmp" err = os.WriteFile(temporary, data, 0644) if err != nil { return err } return os.Rename(temporary, notesFile) } func main() { notes, err := loadNotes() if err != nil { fmt.Println("Error:", err) return } fmt.Println("Notes found:", len(notes)) notes = append(notes, note{Text: "Another note"}) err = saveNotes(notes) if err != nil { fmt.Println("Error:", err) return } fmt.Println("Notes saved:", len(notes)) }