Initial commit

This commit is contained in:
NortPerm
2023-10-30 15:21:12 +03:00
committed by GitHub
commit 13e2575b4e
149 changed files with 3961 additions and 0 deletions

View File

View File

@@ -0,0 +1,65 @@
## Домашнее задание №9 «Валидатор структур»
Необходимо реализовать функцию:
```golang
func Validate(v interface{}) error
```
Она должна валидировать публичные поля входной структуры на основе структурного тэга `validate`.
Функция может возвращать
- или программную ошибку, произошедшую во время валидации;
- или `ValidationErrors` - ошибку, являющуюся слайсом структур, содержащих имя поля и ошибку его валидации.
Таким образом, нужно накопить все ошибки валидации, а не прерывать валидацию на первой ошибке.
Если у поля нет структурных тэгов или нет тэга `validate`, то функция игнорирует его.
Типы полей, которые обязательно должны поддерживаться:
- `int`, `[]int`;
- `string`, `[]string`.
ри желании можно дополнительно поддержать любые другие типы (на ваше усмотрение)._
Необходимо реализовать следующие валидаторы:
- Для строк:
* `len:32` - длина строки должна быть ровно 32 символа;
* `regexp:\\d+` - согласно регулярному выражению строка должна состоять из цифр
(`\\` - экранирование слэша);
* `in:foo,bar` - строка должна входить в множество строк {"foo", "bar"}.
- Для чисел:
* `min:10` - число не может быть меньше 10;
* `max:20` - число не может быть больше 20;
* `in:256,1024` - число должно входить в множество чисел {256, 1024};
- Для слайсов валидируется каждый элемент слайса.
ри желании можно дополнительно добавить парочку новых правил (на ваше усмотрение)._
Допускается комбинация валидаторов по логическому "И" с помощью `|`, например:
* `min:0|max:10` - число должно находится в пределах [0, 10];
* `regexp:\\d+|len:20` - строка должна состоять из цифр и иметь длину 20.
**(\*) Дополнительное задание: поддержка валидации вложенных по композиции структур.**
```golang
type User struct {
m Meta `validate:"nested"`
}
```
### Критерии оценки
- Пайплайн зелёный - 3 балла
- Добавлены юнит-тесты - до 4 баллов
- Понятность и чистота кода - до 3 баллов
- Дополнительное задание на баллы не влияет
#### Зачёт от 7 баллов
### Подсказки
- `reflect.StructTag`
- `regexp.Compile`
- `errors.Is`
### Частые ошибки
- Отсутствует проверка на то, что входной `interface{}` - структура.
- Нет разделения на программные ошибки (неверный тэг, регулярка и пр.) и ошибки валидации.
- Ошибки валидации не вынесены в отдельные переменные и не завраплены.
- Соответственно в тестах не используется `errors.Is` / `errors.As`.

View File

@@ -0,0 +1,3 @@
module github.com/fixme_my_friend/hw09_struct_validator
go 1.19

View File

@@ -0,0 +1,17 @@
package hw09structvalidator
type ValidationError struct {
Field string
Err error
}
type ValidationErrors []ValidationError
func (v ValidationErrors) Error() string {
panic("implement me")
}
func Validate(v interface{}) error {
// Place your code here.
return nil
}

View File

@@ -0,0 +1,60 @@
package hw09structvalidator
import (
"encoding/json"
"fmt"
"testing"
)
type UserRole string
// Test the function on different structures and other types.
type (
User struct {
ID string `json:"id" validate:"len:36"`
Name string
Age int `validate:"min:18|max:50"`
Email string `validate:"regexp:^\\w+@\\w+\\.\\w+$"`
Role UserRole `validate:"in:admin,stuff"`
Phones []string `validate:"len:11"`
meta json.RawMessage //nolint:unused
}
App struct {
Version string `validate:"len:5"`
}
Token struct {
Header []byte
Payload []byte
Signature []byte
}
Response struct {
Code int `validate:"in:200,404,500"`
Body string `json:"omitempty"`
}
)
func TestValidate(t *testing.T) {
tests := []struct {
in interface{}
expectedErr error
}{
{
// Place your code here.
},
// ...
// Place your code here.
}
for i, tt := range tests {
t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
tt := tt
t.Parallel()
// Place your code here.
_ = tt
})
}
}