JSON REST сервер для управления новостями с двумя основными эндпоинтами:
POST /edit/:Id
- изменение новости по IdGET /list
- список новостей
- Web Framework: Fiber
- Database: PostgreSQL
- ORM: Reform
- Configuration: Viper
- Logging: Zap
- Dependency Injection: Uber FX
-- Таблица новостей
CREATE TABLE "News" (
"Id" BIGSERIAL PRIMARY KEY,
"Title" VARCHAR(255) NOT NULL,
"Content" TEXT NOT NULL
);
-- Таблица категорий
CREATE TABLE "Categories" (
"Id" BIGSERIAL PRIMARY KEY,
"Name" VARCHAR(100) NOT NULL UNIQUE,
"Description" TEXT,
"CreatedAt" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
"UpdatedAt" TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Таблица связи новостей и категорий
CREATE TABLE "NewsCategories" (
"NewsId" BIGINT NOT NULL,
"CategoryId" BIGINT NOT NULL,
PRIMARY KEY ("NewsId", "CategoryId"),
FOREIGN KEY ("NewsId") REFERENCES "News"("Id") ON DELETE CASCADE,
FOREIGN KEY ("CategoryId") REFERENCES "Categories"("Id") ON DELETE CASCADE
);
Получение списка новостей с пагинацией.
Query параметры:
limit
(опционально) - количество записей (по умолчанию 10)offset
(опционально) - смещение (по умолчанию 0)
Пример ответа:
{
"Success": true,
"News": [
{
"Id": 64,
"Title": "Lorem ipsum",
"Content": "Dolor sit amet <b>foo</b>",
"Categories": [1,2,3]
}
]
}
Изменение новости по ID.
Параметры пути:
Id
- ID новости для редактирования
Тело запроса:
{
"Id": 64,
"Title": "Lorem ipsum",
"Content": "Dolor sit amet <b>foo</b>",
"Categories": [1,2,3]
}
Примечание: Если какое-то из полей не задано - это поле не будет обновлено.
Пример ответа:
{
"Success": true
}
Получение списка всех категорий с пагинацией.
Query параметры:
limit
(опционально) - количество записей (по умолчанию 10)offset
(опционально) - смещение (по умолчанию 0)
Пример ответа:
{
"success": true,
"categories": [
{
"id": 1,
"name": "Technology",
"description": "Technology related news",
"created_at": "2025-07-20T09:56:38.619586Z",
"updated_at": "2025-07-20T09:56:38.619586Z"
}
],
"total": 5
}
Получение категории по ID.
Параметры пути:
id
- ID категории
Пример ответа:
{
"success": true,
"category": {
"id": 1,
"name": "Technology",
"description": "Technology related news",
"created_at": "2025-07-20T09:56:38.619586Z",
"updated_at": "2025-07-20T09:56:38.619586Z"
}
}
Создание новой категории.
Тело запроса:
{
"name": "Science",
"description": "Scientific discoveries and research"
}
Пример ответа:
{
"success": true,
"category": {
"id": 6,
"name": "Science",
"description": "Scientific discoveries and research",
"created_at": "2025-07-20T13:01:40.913797Z",
"updated_at": "2025-07-20T13:01:40.913797Z"
}
}
Обновление категории.
Параметры пути:
id
- ID категории для обновления
Тело запроса:
{
"name": "Technology Updated",
"description": "Updated technology description"
}
Пример ответа:
{
"success": true,
"category": {
"id": 1,
"name": "Technology Updated",
"description": "Updated technology description",
"created_at": "2025-07-20T09:56:38.619586Z",
"updated_at": "2025-07-20T13:01:40.937882Z"
}
}
Удаление категории.
Параметры пути:
id
- ID категории для удаления
Пример ответа:
{
"success": true,
"message": "Category deleted successfully"
}
Получение категорий для конкретной новости.
Параметры пути:
id
- ID новости
Пример ответа:
{
"success": true,
"categories": [
{
"id": 1,
"name": "Technology",
"description": "Technology related news",
"created_at": "2025-07-20T09:56:38.619586Z",
"updated_at": "2025-07-20T09:56:38.619586Z"
}
],
"total": 1
}
git clone <repository-url>
cd go_news_server
# Создайте базу данных PostgreSQL
createdb news_db
# Примените схему
psql -d news_db -f database/schema.sql
# Скопируйте пример файла
cp env.example .env
# Отредактируйте .env файл под ваши настройки
go mod download
go run cmd/go_news_server/main.go
Все настройки выполняются через переменные окружения:
DB_HOST
- хост базы данных (по умолчанию localhost)DB_PORT
- порт базы данных (по умолчанию 5432)DB_USER
- пользователь базы данныхDB_PASSWORD
- пароль базы данныхDB_NAME
- имя базы данныхDB_MAX_OPEN_CONNS
- максимальное количество открытых соединений (по умолчанию 50)DB_MAX_IDLE_CONNS
- максимальное количество неактивных соединений (по умолчанию 20)DB_CONN_MAX_LIFETIME
- время жизни соединения в минутах (по умолчанию 5)
SERVER_HOST
- хост сервера (по умолчанию localhost)SERVER_PORT
- порт сервера (по умолчанию 8080)SERVER_READ_TIMEOUT
- таймаут чтения в секундах (по умолчанию 15)
level
- уровень логирования (по умолчанию -1)encoding
- формат логирования (console/json)info_filename
- файл для информационных логовerror_filename
- файл для логов ошибок
- Connection Pool: Настроен пул соединений с базой данных для оптимизации производительности
- Graceful Shutdown: Корректное завершение работы сервера
- Dependency Injection: Использование Uber FX для управления зависимостями
- Structured Logging: Логирование с использованием Zap
- Error Handling: Грамотная обработка ошибок
- Configuration Management: Централизованное управление конфигурацией через Viper
- CRUD Operations: Полный набор операций для управления категориями
- Validation: Валидация входных данных и проверка уникальности
go_news_server/
├── cmd/go_news_server/ # Точка входа приложения
├── config/ # Конфигурационные файлы
├── database/ # SQL скрипты
├── internal/ # Внутренний код приложения
│ ├── handlers/ # HTTP обработчики
│ ├── middleware/ # Промежуточное ПО
│ ├── models/ # Модели данных
│ ├── repository/ # Слой доступа к данным
│ ├── routes/ # Маршрутизация
│ ├── server/ # Настройки сервера
│ └── services/ # Бизнес-логика
├── pkg/ # Переиспользуемые пакеты
│ ├── config/ # Конфигурация
│ └── logging/ # Логирование
└── logs/ # Логи приложения
Проект полностью протестирован и работает корректно:
- GET /list - получение списка новостей работает корректно
- POST /edit/:Id - обновление новостей работает корректно
- Частичное обновление - если поле не задано, оно не обновляется
- Пагинация - параметры limit и offset работают корректно
- Обработка ошибок - неверные ID возвращают HTTP 400
- GET /categories - получение списка категорий работает корректно
- GET /categories/:id - получение категории по ID работает корректно
- POST /categories - создание категории работает корректно
- PUT /categories/:id - обновление категории работает корректно
- DELETE /categories/:id - удаление категории работает корректно
- GET /news/:id/categories - получение категорий для новости работает корректно
- Валидация - проверка уникальности имен категорий
- Пагинация - работает для списка категорий
- Подключение к PostgreSQL - работает через Docker контейнер
- Connection Pool - настроен и работает
- Логирование - структурированные логи с Zap
- Конфигурация - через переменные окружения
- Docker - контейнеризация работает корректно
- Dependency Injection - Uber FX настроен корректно
- Статический анализ кода - настроен и используется golangci-lint
Получение списка новостей:
{
"Success": true,
"News": [
{
"id": 1,
"title": "Test News",
"content": "Test content",
"categories": [1, 2, 3]
}
]
}
Получение списка категорий:
{
"success": true,
"categories": [
{
"id": 1,
"name": "Technology",
"description": "Technology related news",
"created_at": "2025-07-20T09:56:38.619586Z",
"updated_at": "2025-07-20T09:56:38.619586Z"
}
],
"total": 5
}
Обновление новости:
{
"Success": true
}
Создание категории:
{
"success": true,
"category": {
"id": 6,
"name": "Science",
"description": "Scientific discoveries",
"created_at": "2025-07-20T13:01:40.913797Z",
"updated_at": "2025-07-20T13:01:40.913797Z"
}
}
Ошибка при неверном ID:
HTTP 404 Not Found
{"message":"Category not found","success":false}
# Установка и настройка
make install
make setup-db
# Разработка
make dev
make test
# Сборка и запуск
make build
make run
# Docker
make docker-build
make docker-run