// Package guestbook keeps the messages, checks new ones, and saves them to a // JSON file. It knows nothing about the web. package guestbook import "errors" const MaxNameLength = 40 const MaxTextLength = 500 // Message is one entry. The fields are exported because encoding/json and // html/template can only see exported fields. type Message struct { Name string Text string } // NewMessage trims and checks the values. Its error is safe to show a visitor. func NewMessage(name string, text string) (Message, error) { // TODO: trim both values. An empty value or a value that is too long is an // error. Otherwise return the message and nil. return Message{}, errors.New("TODO: NewMessage is not written yet.") } // Book holds the messages. Make one with Open. Its methods may be called by // many requests at the same time. type Book struct { // TODO: add a sync.Mutex, the file name, and a slice of messages. } // Open loads the book from a file. A file that does not exist yet gives an empty // book. A file that cannot be read or understood is an error. func Open(filename string) (*Book, error) { // TODO: read the file, and treat os.ErrNotExist as an empty book. return &Book{}, nil } // Messages returns a copy of the messages, oldest first. func (b *Book) Messages() []Message { // TODO: lock, and return a copy of the slice. return []Message{} } // Add saves a message. If saving fails, the book stays as it was. func (b *Book) Add(message Message) error { // TODO: lock, make the longer slice, save it, and only then keep it. return errors.New("TODO: Add is not written yet") } // TODO: add a helper that writes the messages to a temporary file as JSON, and // renames it over the real file.