# Koenig (25.07.2013 / 16:38)
L!MP, опять те предложу гостевую на обзор, самое то чтоб было понять некоторые вещи
Дело было вечером, делать было не чего.
Вобщем вот, некое подобие гостевой книги: имя + текст, валидация на пустые значения, удаление сообщений, вывод сообщений (без обратной сортировки сообщений, ибо просто так это не сделаешь, код бы прилично увеличился и хуже воспринимался)
Сами сообщения хранятся в памяти процесса.
package main
import (
"fmt"
"net/http"
"strconv"
"strings"
"time"
)
// структура сообщения
type Message struct {
Name string
Text string
Time time.Time
}
// функция получения форматированой даты
func (m *Message) Date() string {
return m.Time.Format("01.02.2006 в 15:04")
}
// "слайс" для хранения сообщений
var messages = []*Message{}
// функция - обертка которая обеспечивает общий функционал http обработчиков
// конкретная функция-обработчик передается в аогумент handler и оборачивается в лямбду тем самым
// обеспечивается ее "ленивая" инициализация
func MakeHandler(handler func(http.ResponseWriter, *http.Request)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// устанавливаем http заголовки
w.Header().Set("Content-Type", "text/html; charset=UTF-8")
w.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate")
// запускаем обработчик
handler(w, r)
}
}
// http обработчик,
// вывод списка сообщений
func Index(w http.ResponseWriter, r *http.Request) {
// рисуем форму ...
fmt.Fprintf(w, `<form action="add" method="post">`)
fmt.Fprintf(w, `<input type="text" name="name" value="Гость"> `)
fmt.Fprintf(w, `<input type="text" name="text" value=""> `)
fmt.Fprintf(w, `<input type="submit" value="Написать">`)
fmt.Fprintf(w, `</form><hr>`)
// циклом проходимя по слайсу и выводим сообщения
for i, message := range messages {
fmt.Fprintf(w, `<p><b>%s</b> (%s): %s `, message.Name, message.Date(), message.Text)
fmt.Fprintf(w, `[ <a href="del?i=%d">удалить</a> ]</p>`, i)
}
}
// http обработчик,
// добавление нового сообщения
func Add(w http.ResponseWriter, r *http.Request) {
// получаем значения "name" и "text" из формы и обрезаем лишние пробелы по краям
name := strings.Trim(r.FormValue("name"), " ")
text := strings.Trim(r.FormValue("text"), " ")
// если обе переменные имеют не пустые значения,
// то создаём новую структуру Message с переданными значениями
// и добавляем её в слайс
if name != "" && text != "" {
messages = append(messages, &Message{Name: name, Text: text, Time: time.Now()})
}
http.Redirect(w, r, "/", http.StatusFound)
}
// http обработчик,
// удаление сообщения по идентификатору
func Del(w http.ResponseWriter, r *http.Request) {
// получаем GET парамметр и приволим его к числовому типу
if i, err := strconv.Atoi(r.FormValue("i")); err == nil {
// просто взять и удалить эллемент слайса по ключу не получиться
// по этому мы "обрезаем" слайс ДО и ПОСЛЕ нужного ключа и собираем обратно
messages = append(messages[:i], messages[i+1:]...)
}
http.Redirect(w, r, "/", http.StatusFound)
}
func main() {
http.HandleFunc("/", MakeHandler(Index))
http.HandleFunc("/add", MakeHandler(Add))
http.HandleFunc("/del", MakeHandler(Del))
http.ListenAndServe(":9000", nil)
}