Сорок третий урок курса по Go. Читатель закрыл вкладку — и обработчик узнаёт об этом сам: измерено, как он бросает работу через двести миллисекунд. Срок на запрос к базе, ключ своего типа вместо строки и обещанный переезд вошедшего человека в контекст запроса.
Сорок второй урок курса по Go. Сервер конкурентен с урока про HTTP, и вы этого не выбирали: каждый запрос — своя горутина. Измерено, как счётчик без замка сначала теряет один просмотр из пятисот, а потом роняет весь сервер, и как go test -race находит это заранее.
Сорок первый урок курса по Go. Обещанная в уроке 10 таблица: случаи складывают в список, `t.Run` даёт каждому имя, и провал сразу говорит, какой именно случай сломался. Плюс проверка обработчика без запуска сервера и честный разговор о том, что показывает `-cover`.
Сороковой урок курса по Go. Форма, в которой едет файл, и четыре вещи, которые проверяют до того, как он ляжет на диск: размер, тип по содержимому, собственное имя вместо присланного и место, куда его класть. Заодно приводим /static в порядок: brand, css, images, js, uploads.
Тридцать девятый урок курса по Go. Чужой скрипт на вашей странице и чужой сайт, отправляющий форму от имени вашего читателя. Измерено, как html/template экранирует по месту — в тексте, в ссылке и внутри script, — и как жетон отличает вашу форму от чужой.
Тридцать восьмой урок курса по Go. Спрятать кнопку — не защита: измерено, как чужой человек правит вашу статью прямым запросом, пока кнопки он не видит. Проверка живёт в обработчике и в одном месте, а отказы отвечают по-разному: гостю — на вход, чужому — 403, несуществующему — 404.
Тридцать седьмой урок курса по Go. HTTP не помнит ничего: каждый запрос приходит от незнакомца. Печенье с номером пользователя подделывается за секунду. Поэтому в браузер уходит случайный токен, а в базу его хеш, и всё закрывается тремя словами: HttpOnly, Secure, SameSite.
Тридцать шестой урок курса по Go. Пароль в базе не хранят — хранят bcrypt-хеш, у которого соль внутри, а стоимость снаружи. Измерено: sha256 даёт девять миллионов хешей в секунду, bcrypt десять. Плюс предел в 72 байта, о который казахский пароль спотыкается уже на тридцать седьмой букве.
Тридцать пятый урок курса по Go. Семь шаблонов блога держат семь копий одного и того же начала страницы. Сегодня остаётся одна рамка: base с блоками, папки pages и partials, семантическая разметка — и измеренная ловушка, из-за которой у людей все страницы вдруг показывают одну и ту же.
Тридцать четвёртый урок курса по Go. Работающий поиск по блогу: виртуальная таблица FTS5, три триггера, ранжирование и подсветка найденного. И измеренный сюрприз: параметр защищает от инъекции, но не от того, что человек напечатал в строку поиска слово OR.
Тридцать третий урок курса по Go. У статьи много тегов, у тега много статей — и хранится это отдельной таблицей, а не списком в колонке. Составной ключ, on conflict ради id, каскад при удалении. И обещанный способ спросить у ошибки её код вместо того, чтобы читать её текст.
Тридцать второй урок курса по Go. Два правила, на которых держится база. Данные не склеивают с текстом запроса: подстроенный адрес возвращает три строки вместо одной, а через параметр — ноль. Что должно случиться вместе — в транзакцию: без неё счётчик вырос за переезд, которого не было.
Тридцать первый урок курса по Go. Схему перестаёт создавать программа при старте: появляются нумерованные файлы миграций, журнал применённого и правило «каждая ровно один раз». Плюс измеренная ловушка: колонку not null без значения по умолчанию пустая база примет, а рабочая откажется менять.
Тридцатый урок курса по Go. Статьи переезжают из среза в базу и переживают перезапуск. Тип Store, который прячет базу от остального кода, четыре действия над статьёй и одна неочевидная вещь, стоящая целого раздела: обновить то, чего нет, — не ошибка, и узнать об этом можно только по RowsAffected.
Двадцать восьмой урок курса по Go. У статьи появляются комментарии, и они не помещаются внутрь неё. Вторая таблица и ключ между ними, join против left join, каскадное удаление и ловушка SQLite, из-за которой внешние ключи молчат и оставляют строки сиротами.
Двадцать седьмой урок курса по Go. Статьи наконец переживут перезапуск. Почему в курсе SQLite, а не Postgres, как создать таблицу и положить в неё строку: insert с returning, select с where и order by, update, у которого забыли where, и разница между = null и is null.
Двадцать девятый урок курса по Go. Блог наконец читает статьи из файла базы. Пакет и драйвер, почему sql.Open ничего не открывает, что такое пул соединений и почему прагму про внешние ключи пишут в строку подключения, а не отдельным запросом. Плюс ErrNoRows и проверка ошибки после цикла.
Двадцать шестой урок курса по Go. Адрес, файл базы и ключ подписи уезжают из кода. Пакет flag и что даёт -h, почему переменную окружения удобно делать значением флага по умолчанию, чем пустая переменная отличается от незаданной и почему без обязательной настройки надо падать при старте.