API-сервис для управления вопросами и ответами, построенный на Go с использованием GORM, PostgreSQL и Docker.
- Go 1.25
- GORM - ORM для работы с базой данных
- PostgreSQL - реляционная база данных
- Goose - миграции базы данных
- net/http - стандартная библиотека HTTP (без внешних роутеров)
- Zap - структурированное логирование
- testify - библиотека для тестирования
- Docker - контейнеризация
Проект следует Clean Architecture принципам:
backend/
├── cmd/main.go # Точка входа
├── config/ # Конфигурация
├── internal/
│ ├── entity/ # Сущности домена
│ ├── port/ # Интерфейсы (порты)
│ │ ├── repo/ # Интерфейсы репозиториев
│ │ └── service/ # Интерфейсы сервисов
│ ├── cases/ # Бизнес-логика (use cases)
│ ├── adapter/ # Адаптеры
│ │ └── repo/ # Реализация репозиториев
│ └── input/ # Входные точки
│ └── http/ # HTTP handlers
└── pkg/
└── migration/ # Миграции базы данных
GET /questions/- получить список всех вопросовPOST /questions/- создать новый вопросGET /questions/{id}- получить вопрос и все ответы на негоDELETE /questions/{id}- удалить вопрос (вместе с ответами)
POST /questions/{id}/answers/- добавить ответ к вопросуGET /answers/{id}- получить конкретный ответDELETE /answers/{id}- удалить ответ
- Клонируйте репозиторий:
git clone <repository-url>
cd HiTalent_TestTask- Запустите приложение через docker-compose:
docker-compose up --buildПриложение будет доступно по адресу http://localhost:8080
-
Убедитесь, что у вас установлены Go 1.21+ и PostgreSQL
-
Установите зависимости:
go mod download- Создайте файл
.envв корне проекта:
POSTGRES_CONNECTION_STRING=host=localhost user=your_user password=your_password dbname=your_db sslmode=disable port=5432
HTTP_PORT=8080-
Запустите миграции (они применяются автоматически при старте приложения)
-
Запустите приложение:
go run backend/cmd/main.gocurl -X POST http://localhost:8080/questions/ \
-H "Content-Type: application/json" \
-d '{"text": "Что такое Go?"}'curl http://localhost:8080/questions/curl http://localhost:8080/questions/1curl -X POST http://localhost:8080/questions/1/answers \
-H "Content-Type: application/json" \
-d '{"user_id": "user-123", "text": "Go - это язык программирования"}'curl http://localhost:8080/answers/1curl -X DELETE http://localhost:8080/questions/1curl -X DELETE http://localhost:8080/answers/1- Каскадное удаление: при удалении вопроса автоматически удаляются все его ответы
- Валидация: нельзя создать ответ к несуществующему вопросу
- Множественные ответы: один пользователь может оставлять несколько ответов на один вопрос
- Структурированное логирование с использованием Zap
- Автоматические миграции при запуске приложения
id- первичный ключ (SERIAL)text- текст вопроса (TEXT, NOT NULL)created_at- время создания (TIMESTAMP, DEFAULT NOW())
id- первичный ключ (SERIAL)question_id- внешний ключ на questions (INTEGER, NOT NULL)user_id- идентификатор пользователя (VARCHAR(255), NOT NULL)text- текст ответа (TEXT, NOT NULL)created_at- время создания (TIMESTAMP, DEFAULT NOW())
Проект включает комплексные unit-тесты с использованием httptest и testify:
- Покрытие кода: 71.5%
- Количество тестов: 28
- Технологии:
httptest,testify/assert,testify/require
# Запустить все тесты
go test ./backend/...
# Запустить тесты с выводом подробной информации
go test ./backend/... -v
# Запустить тесты с покрытием кода
go test ./backend/... -cover
# Запустить тесты для конкретного пакета
go test ./backend/internal/input/http/server/... -vВопросы (Questions):
- Получение списка вопросов (включая пустой список)
- Создание вопроса
- Валидация при создании (пустой текст)
- Получение вопроса по ID
- Получение вопроса с ответами
- Обработка несуществующего вопроса
- Удаление вопроса
- Проверка CreatedAt
Ответы (Answers):
- Создание ответа
- Валидация при создании (пустой текст, пустой UserId)
- Создание ответа к несуществующему вопросу
- Получение ответа по ID
- Обработка несуществующего ответа
- Удаление ответа
- Несколько ответов от одного пользователя
- Проверка CreatedAt
Дополнительные тесты:
- Обработка невалидных HTTP методов
- Обработка невалидных ID
- Обработка невалидного JSON
- Получение вопроса с несколькими ответами
Для изоляции тестов от базы данных используются in-memory репозитории:
memory.QuestionRepo- реализация репозитория вопросов в памятиmemory.AnswerRepo- реализация репозитория ответов в памяти
Это позволяет запускать тесты быстро и независимо от внешних зависимостей.
Приложение использует структурированное логирование через Zap. Все операции (создание, чтение, удаление) логируются с соответствующим уровнем детализации.