Ошибки часто приводят в ярость, но часто самые раздражающие ошибки оказываются самыми интересными. Я собираюсь кратко обсудить ошибку, которая вызвала много головной боли. Но в процессе мы многое узнали о системе типов Go и о том, как некоторые популярные библиотеки Go справляются с некоторыми неоднозначностями.

Одна из функций, над которой мы работаем, - это веб-среда разработки SQL. На самом деле это довольно круто. Он подключается к хранилищу данных Redshift пользователей и позволяет им безопасно писать запросы и просматривать данные в удобном формате. Также вывод данных в разные места и в различных форматах.

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

Мы немного покопались и заметили, что данные в кодировке base64, похоже, исходят от службы Go, которая выполняла запросы. Мы разместили несколько журналов здесь и там и заметили, что запрос возвращает «[] uint8 {51, 48, 48}« вместо числа «300». Затем, когда мы попытались маршалировать данные в JSON для отправки обратно в браузер. Этот байтовый массив преобразовывался в строку base64.

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

Я покопался, поговорил с несколькими людьми на канале Go Slack. Оказывается, что байтовый массив, возвращаемый драйвером Postgresql `lib / pg`, вызван тем, что автор справедливо не хотел предполагать, какой тип целого числа вы ожидали, поскольку преобразование между типами могло вызвать неточности и неточности. Драйвер возвращает массив символов для каждой цифры числового значения, возвращаемого Postgres. В моем случае `51, 48, 48` -› `300`. Итак, все, что мне нужно было сделать, это проверить, является ли значение []byte , и просто обернуть его как строку `string (rawVal)`. Это одна загадка разгадана! Но почему он возвращал строку base64?

После того, как моя команда поработала еще раз, функция json.Marshal не знает, что делать с байтовым массивом, поэтому считает, что это двоичные данные. Функция Marshal не имеет точного совпадения с массивом байтов с точки зрения преобразования типов, поэтому вместо этого она преобразуется в base64, пытаясь сохранить данные.

Итак, вот оно, это странное поведение действительно имеет большой смысл. Это также связано с тем, что мы пытались иметь дело с свободными типами, используя множество указателей, интерфейсов и отражений, которые вы всегда должны использовать с осторожностью в Go. В конце концов, это язык с сильным типированием, поэтому любые попытки «обойти» это без осторожности могут привести к неприятностям!

Другие подобные статьи можно найти в Peak Content Hub.