Учебное пособие по отражениям: строка запроса для структурирования синтаксического анализатора в Go.

Когда нам нужно работать с переменными во время выполнения, используя информацию, которой не было на момент написания программы, или нам может потребоваться создать переменные во время выполнения для тестовых случаев, в этих ситуациях нам может потребоваться отражение. Отражение станет вашим незаменимым инструментом, когда вы работаете с универсальным дизайном.

Вкратце, Reflections позволяет исследовать, изменять и создавать переменные, структуры и функции во время выполнения программы.

В этом руководстве мы планируем создать собственный запрос GET для синтаксического анализатора структуры, чтобы понять, как можно использовать отражения в go lang.

Прежде чем мы начнем, нам нужно узнать, как найти тип переданного interface{} type.

Если мы посмотрим на функцию выше, мы принимаем входные данные как динамический тип interface{} в go. Простое замечание: если вы найдете библиотеку, которая использует interface{}, она наверняка может использовать отражения в качестве своего внутреннего механизма.

  • reflect.TypeOf(d) создает объект reflect.Type с Kind в качестве типа переменной, переданной в функцию.
  • td.Kind() получает тип переменной. Тип можно сравнить с константами, присутствующими в пакете отражения, то есть со всеми базовыми типами, доступными в go like; Int, Uint, Func, Interface, Map, Ptr и т. Д.

Когда мы когда-либо хотим работать с типами, мы используем reflect.TypeOf для преобразования в reflect.Type, а затем выполняем с ними различные операции, например, мы можем создать новую переменную с помощью reflect.New, которая вернет переменную с заданным типом.

HTTP СЕРВЕР

Теперь давайте начнем с создания базового http сервера, который будет служить точкой для обработки запросов GET. Это просто;

http.HandleFunc("/map-it", HandleGetMapping)
http.ListenAndServe(":5000", nil)

Где может выглядеть функция HandleGetMapping;

// HandleGetMapping handles get request
func HandleGetMapping(w http.ResponseWriter, req *http.Request) {
 fmt.Fprintf(w, "got %v", req.URL.Query().Get("hello"))
}

Давайте создадим наш тип структуры с with, который будет действовать как структура-держатель для нашего запроса на получение.

// Article data type
type Article struct {
 Title string `mapper:"title" json:"title"`
 Body  string `mapper:"body" json:"body"`
 JSON  string `mapper:"json" json:"json"`
}

Здесь тип тега mapper - это наш настраиваемый тип, который мы будем использовать позже для отображения ключа запроса в структуру. т.е.

http://localhost:8080/map-it?title=title&body=bo&json={"A":"a"}

отображается в приведенную выше структуру.

ФУНКЦИЯ КАРТИРОВАНИЯ

Итак, давайте создадим еще одну функцию с именем MapIt, которая принимает указатель interface{} и сопоставляет предоставленную структуру с данными из запроса получения.

Взглянув на приведенную выше функцию, мы можем это увидеть;

  • dhVal := reflect.ValueOf(d) создает значение, отражающее тип, с помощью которого мы можем установить или получить значение. Основное различие между reflect.TypeOf и reflect.ValueOf заключается в том, что с помощью значения варианта мы можем получить или установить значение переменной, но с помощью TypeOf мы можем получить только информацию о типе значения.
  • Поскольку мы передаем ссылку на значение в d, нам нужно отменить ссылку на указатель, чтобы получить / установить в него значение, что выполняется с помощью dType.Elem(). Но поскольку dType.Elem() - это структура, мы можем получить количество полей, присутствующих в структуре, и поместить его в цикл, используя функцию NumField.
  • Чтобы получить значение тега, присутствующее в поле структуры reflect.StructField, мы можем использовать метод Tagstructs Get для получения ключа.
  • Наконец, функция result.SetString используется для установки строкового значения, которое мы получили от req.URL.Query().Get(key). Для установки различных других типов данных мы можем: SetInt, Set функции, присутствующие в поле структуры.

Давайте воспользуемся этой функцией, чтобы завершить нашу HandleGetMapping функцию, которая выглядит следующим образом (просто базовый обработчик, здесь ничего особенного);

  • Здесь мы используем функцию MapIt, определенную ранее, и передаем на нее ссылку во входную структуру.
  • Мы используем json.Marshal для преобразования отображаемой структуры в jsonData для предоставления ответа пользователю.

НАКОНЕЦ

Итак, после объединения всех функций весь наш сервер выглядит так:

После запуска этого сценария мы можем найти это;

http://localhost:5000/map-it?title=Awesome%20Title&body=sample%20body&json={%22A%22:%22a%22}

отображается в структуру и маршалируется обратно в строку на выходе;

{
  "title": "Awesome Title",
  "body": "sample body",
  "json": "{\"A\":\"a\"}"
}

Итак, таким образом мы можем посмотреть, как мы сопоставили параметр запроса получения с структурой перехода с помощью отражения. Это всего лишь базовый пример использования отражения. Для более сложных примеров мы можем посмотреть; json.Marshal функция, которая использует отражение для преобразования структуры в строковое значение json.

Для более полного кода с использованием gin framework вы можете заглянуть в https://github.com/dipeshdulal/learning-golang/tree/master/structparser

Вот и все. Удачного кодирования.

Подробнее об отражениях читайте здесь;

Https://medium.com/capital-one-tech/learning-to-use-go-reflection-part-2-c91657395066

Следуйте за мной на GitHub: https://github.com/dipeshdulal

Для получения дополнительных образцов по основам проверки голанга; Https://github.com/dipeshdulal/learning-golang

Аригату あ り が と う