Привет, мы создаем новый язык выражений для управления структурными данными 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