Привет, мы создаем новый язык выражений для управления структурными данными Golang. Код проекта размещен на https://github.com/lysu/go-el.
Его основная цель - найти Reflect.Value по выражению, а затем прочитать и написать. Это очень полезно для создания HTTP Patch API.
Установка
Просто, как это требуется, чтобы ввести следующую команду:
go get github.com/lysu/go-el
и импортировать с
import github.com/lysu/go-el
использование
Пример данных
Например, у нас есть такие данные:
type Comment struct { NickName string Content string Date time.Time } type Author struct { Name string } type Blog struct { Title string RoleState map[string]uint CommentIds []uint64 Comments map[string]*Comment } func (b Blog) FirstComment() *Comment { return b.Comments["0"] }
затем мы инициализируем их некоторыми тестовыми данными:
b := &Blog{ Title: "Blog title1", CommentIds: []uint64{1, 3}, Comments: map[string]*Comment{ "0": { NickName: "000", Content: "test", Date: time.Now(), }, "1": { NickName: "u1", Content: "test", Date: time.Now(), }, "3": { NickName: "tester", Content: "test hehe...", Date: time.Now(), }, }, Author: Author{ Name: "Author 1", }, RoleState: map[string]uint{}, }
Выражение
Используя el.Expression, мы можем перейти от root(b) к любому месту в этой структуре.
1. В поле
exp := el.Expression("Title") v, _ := exp.Execute(&data) fmt.Printf("%v\n", v.interface()) //==> Blog title1
2. Во вложенное поле
exp := el.Expression("Author.Name") v, _ := exp.Execute(&data) fmt.Printf("%v\n", v.interface()) //==> Author 1
3. Чтобы нарезать/массив/строковый элемент
exp := el.Expression("CommentIds[0]") v, _ := exp.Execute(&data) fmt.Printf("%v\n", v.interface()) //==> 1
4. Чтобы сопоставить элемент
exp := el.Expression("Comments["3"].NickName") v, _ := exp.Execute(&data) fmt.Printf("%v\n", v.interface()) //==> tester
5. Элемент в [] также может быть другим выражением
exp := el.Expression("Comments[CommentIds[0]].NickName") v, _ := exp.Execute(&data) fmt.Printf("%v\n", v.interface()) //==> u1
6. Функция вызова
функция может вернуть только ОДИН результат
exp := el.Expression("FirstComment().Content") v, _ := exp.Execute(&data) fmt.Printf("%v\n", v.interface()) //==> test
7. Изменить значение
После выражения Execute мы получили relfect.Value, мы также можем использовать его для изменения данных, например.
exp := el.Expression("FirstComment().Content") v, _ := exp.Execute(&data) v.SetString("1111")
позволит первому комментарию со значением 1111
Кроме того, мы рекомендуем пользователям уделить время просмотру Законов отражения, позаботиться о некоторых ограничениях, которые имеет отражение.
Патчер
Основываясь на Expression, мы также предоставляем инструмент под названием Patcher, цель которого — упростить использование изменения объекта с выражением и его пакетную обработку.
Мы обнаружили, что очень полезно создать HTTP Patch API для частичного обновления объекта.
ps := p.Patch{ "Author.Name": "ほん", "Comments[CommentIds[0]].NickName": "私", "roleState[100]": uint(100), } err := patcher.PatchIt(b, ps)
Это изменит сразу три свойства~ (но мы по-прежнему соблюдаем некоторые правила refect, такие как использование значения карты ptr.. и т. д.)
Более
См. наш пример в Unit-Test:
- "выражение"
- патчер
СДЕЛАТЬ
генерировать выражение между двумя данными.. как diff..- -?
Спасибо
- Много кода взято из flosch/pongo2 — — Классный шаблонизатор
- Презентация Роба Пайка Лексическое сканирование в Go