Golang: Мои Открытия
В этом посте мы обсудим несколько увлекательных моментов, которые я узнал в процессе своей работы. Залетайте в наш канал для GO разработчиков, там много полезного.
1. Как используется встраивание (embedding) в Go?
В Go директива //go:embed используется для встраивания файлов и папок в бинарный файл Go на этапе компиляции. Эта функция улучшает безопасность, производительность и простоту кода за счёт возможности прямого импорта файлов без использования функций операционной системы.
Пример:
Эта директива указывает компилятору Go встроить содержимое каталога frontend/dist в бинарный файл. Префикс all: используется для включения не только файлов из каталога, но и всех вложенных каталогов и их файлов рекурсивно.
var assets embed.FS Это объявляет переменную с именем assets типа embed.FS, который является интерфейсом файловой системы, предоставляемым пакетом embed. Эта переменная будет предоставлять доступ к встроенным файлам во время выполнения.
Преимущество заключается в том, что импортирование определённых файлов напрямую и использование embed вместо функций операционной системы повышает безопасность, производительность и простоту использования.
Можно попробовать использовать это для создания настольного приложения и загрузить все данные, связанные с интерфейсом, в сервер Go.
2. Какая польза от оператора Select в Go?
Оператор select позволяет горутине ожидать выполнения нескольких операций взаимодействия.
Ну, это что-то, что вы могли бы увидеть на https://go.dev/tour/concurrency/5, но в чём здесь польза?
Давайте рассмотрим пример, где мы записываем данные в конечное соединение. В случае закрытия приложения вы не хотите писать в закрытое конечное соединение.
Код не обязательно “останавливается” на ctx.Done(). Оператор select ожидает, когда один из случаев станет готовым. Если контекст отменен (или его срок действия истекает), до того как будет получена ошибка или до того как операция записи будет подтверждена как успешная, тогда случай ctx.Done() будет выполняться первым, что приведет к закрытию destConn и раннему завершению функции и её возврату.
Если контекст не завершён и произошла ошибка, то выполнится случай err = <-errChan1, который залогирует ошибку и вернёт её.
Если контекст не завершён и ошибка не произошла, а операция записи выполнилась успешно первой, то выполнится последний случай, позволяя функции продолжить выполнение за пределами оператора select.
3. Как реализовать интерфейсы в Go?
В Go интерфейс представляет собой тип, который определяет набор сигнатур методов (названия методов, параметры и типы возвращаемых значений), но не реализует сами методы. Это способ определения поведения как набора действий. Тип реализует интерфейс, реализуя все методы, объявленные в интерфейсе.
Реализуйте следующий интерфейс:
Приведенный выше фрагмент кода демонстрирует контракт для получения данных о студенте. Любой тип, который реализует этот интерфейс, может предоставлять данные о студенте, что позволяет легко заменять различные источники данных или реализации без изменения остального кода. Это может быть особенно полезно при работе с различными системами баз данных и внешними службами или при создании заглушек данных для тестирования.
Какова практическая польза от этого? Абстракция, полиморфизм, гибкость и еще много чего.
4. Как init работает в Go?
В Go функция init является специальной функцией, которая автоматически выполняется при инициализации пакета. В каждом пакете может быть одна или несколько функций init, и они выполняются в порядке их появления в файле. Функция init используется для выполнения задач настройки, которые необходимо выполнить перед использованием пакета, таких как инициализация переменных или выполнение другой инициализационной логики.
Какова выгода от этого? Вам не нужно инициализировать функцию init вручную; вам просто нужно импортировать функцию, и значения будут извлечены и назначены.
5. Как работают несколько отложенных вызовов (deferrals)?
Отложенные вызовы работают как стек, что означает “первым вошел, последним вышел” (LIFO). Так что, если кто-то напишет что-то вроде этого:
Таким образом, когда эта функция завершится, сначала будет выполнена функция printCon, затем cleanCon, и, наконец, closeCon.
6. Как использовать слушатель событий в Go?
В приведенном ниже фрагменте кода на Go мы имеем мощный шаблон обработки событий, который облегчает создание отзывчивых приложений.
Регистрация события: runtime.EventsOn – это вызов функции, который регистрирует слушатель событий для события с именем “event:check:health”. Когда это событие срабатывает, вызывается функция (замыкание), предоставленная вторым аргументом.
Излучение события: затем используется runtime.EventsEmit для отправки события с именем responseEventName. Вместе с именем в качестве данных события передается карта, содержащая статус успешности и текущую версию приложения (полученную через config.GetConfig().Version).
В заключение, данный фрагмент кода устанавливает слушатель событий, который при срабатывании события “event:check:health” отвечает другим событием, указывающим на успешность и версию приложения. Это элегантный пример того, как Go может кратко обрабатывать сложные событийно-ориентированные рабочие процессы.
Взято из репозитория Slashbase.
7. Как обрабатывать панику в Go?
В Go паника (panic) – это встроенная функция, которая прекращает обычный поток управления и начинает паниковать. Когда вызывается функция panic, выполнение текущей функции немедленно останавливается, и управление начинает разворачивать стек, выполняя при этом все отложенные функции.
Если паника достигает вершины стека вызовов горутины без восстановления, программа завершается с ненулевым кодом статуса и, как правило, выводит сообщение о панике и стек вызовов в стандартный поток ошибок.
Для обработки паники в Go предоставляется функция recover, которая может остановить последовательность паники и вернуть значение, переданное функции panic. Она полезна только внутри операторов defer, потому что после начала паники это единственный способ вернуть контроль над программой.
Подорожание электроники на 15-20% с первого апреля
С 1 апреля 2024 года прекращает действовать решение Евразийской экономической комиссии (в неё входят Россия, Беларусь, Казахстан, Армения и Киргизия) о повышении порога беспошлинного ввоза товаров с €200 до €1000. Подготовка документов о продлении временной меры так и не началась, передают «Ведомости» со ссылкой на собственные источники, а значит, 1 апреля автоматически вернётся порог в €200. Это грозит сокращением импорта на 18–20 % и подорожанием импортных товаров на 15–20 %.
Порог беспошлинного ввоза товаров в €1000 существовал до 2019 года — речь идёт о норме, которая действует в отношении ввоза товаров физическими лицами для личного пользования. Это значение снижалось несколько раз и с января 2020 года зафиксировалось на отметке в €200.
Размер пошлины, о которой идёт речь, составляет 15 %, и она исчисляется от превышения цены товара. Так, если он стоит €250, то 15 % придётся заплатить от €50 — в итоге товар обойдётся в €257,5. В результате следует ожидать роста цен на технику на российских интернет-площадках на 10–15 %. В первую очередь подорожание коснётся продукции, которая не поставляется в Россию официально:
• периферия для ПК от Razer, Logitech и других брендов;
• устройства Apple — iPhone, iPad, MacBook, AirPods;
• техника Samsung и Dyson;
• телевизоры, за исключением российских и китайских брендов;
• бытовая техника дороже 20 тыс. руб. от LG, Bosch, Tefal, Braun, Sony и др.
Что вы думаете об онлайн-курсах? Поделитесь мнением!
Онлайн-курсов становится все больше, и нам интересно собрать статистику, чтобы лучше понимать запросы читателей Пикабу.
Пожалуйста, поделитесь своим мнением!
Ответ на пост «Тихая обувь»
А вот нас одна организация хочет "обуть" в российские ПК, вместо нормальных.
А вот и...
Преимущества.
Официаоьный скрин с сайта.
Характеристики.
Тихая обувь
Купили российский ноутбук (в реестре Минпромторга), вся краса импортозамещения в BIOS
Упс, 12+ млн API-токенов было найдено на GitHub
🗄Эксперты по кибербезопасности GitGuardian выяснили, что в 2023 году пользователи GitHub случайно раскрыли 12,8 млн аутентификационных и конфиденциальных токенов API. Утечки произошли в более чем 3 млн общедоступных репозиториев.
🗄В частности, на GitHub раскрывали ключи Google API и Google Cloud, MongoDB, токены ботов OpenWeatherMap и Telegram, учётные данные MySQL и PostgreSQL, а также ключи OAuth GitHub. 91,6% данных были доступны пять и более дней.
Тренды раскрытия данных определяются и развитием ИИ. Так, количество утечек ключей API OpenAI на GitHub выросло в 1212 раз по сравнению с 2022 годом. У HuggingFace также резко возросло количество утечек.
🗄В GitGuardian отмечают, что технологии ИИ можно использовать для обнаружения и защиты раскрытых данных. Однако огромные операционные масштабы, стоимость и эффективность идентификации пока ограничивают внедрение таких инструментов.
🗄С 1 марта GitHub по умолчанию активировала защиту от принудительной отправки push-уведомлений для всех общедоступных репозиториев при отправке нового кода. Это позволит предотвратить случайное раскрытие данных, в том числе токенов доступа и ключей API.
Сколько стоит лид — как настроить систему аналитики, если связка Roistat и CRM не помогла
Однажды некоторые технари переходят на тёмную сторону и ищут ответы на дурацкие вопросы: сколько стоит лид, какую прибыль приносит каждый канал с учётом LT пользователей… Да, кстати, а сколько у нас пользователей и какова стоимость их привлечения? А ещё, пожалуйста, посчитайте конверсии в покупку на каждом этапе воронки по каждому из каналов.
Ну и, разумеется, прилагался регулярный бонус от руководителей в виде «уже приехали?», вернее: «а когда сможем увидеть аналитику?»
Расскажу о нашем способе выстроить аналитику от потраченных до заработанных каждым маркетинговым каналом денег с помощью GTM, «Яндекс Метрики», Superset, BILLmanager, Data Layer и кастомных скриптов.
Без аналитики нам не обойтись. UTM-метки годятся для отдельных активностей. А вот чтобы проанализировать, какой канал прибыльный, какой — убыточный, куда инвестировать, как оптимизировать конверсии, проанализировать причины роста или падения продаж, — нужно было забуриться глубже.
Например, каждый раз, когда продажи резко росли или падали, причины приходилось раскапывать руками. Долго и мучительно: копались в Brand Analytics — вдруг упомянул блогер, шли в «Яндекс Метрику» — был ли скачок в SEO, думали — а может, что-то из рекламы. Но узнать точно всё равно было невозможно. А значит, повторить или избежать — тоже никак.Способ работает при нашем легаси и любви к космолётам и не претендует на то, чтобы быть оптимальным для всех. У нас не получилось срастить Roistat, его счётчик на сайте и BILLmanager с помощью стандартных интеграций. А у наших партнёров — вполне.
У коллег Roistat в комплекте с amoCRM работает как часы. Потому что ребята работают почти с каждым клиентом лично и всех заводят в amoCRM. Мы не можем вносить в CRM конечных пользователей: система переполнится записями. Эти клиенты у нас существуют только на уровне биллинга. А CRM есть только для партнёров, с которыми работает отдел продаж. И там своя система аналитики.
Наша схема подойдёт не всем. Тут много рукописных интеграций: ЯМ → BILLmanager, BILLmanager → Superset, ЯМ → Superset. И каждая из них может перестать работать из-за обновлений любого из компонентов. А ещё всё это нужно поддерживать и следить за чистотой данных. Гораздо проще пользоваться нативными интеграциями.
Мы пошли по этому пути, потому что у нас нет CRM в классическом виде для сегмента конечных клиентов: наш продукт продаётся автоматизированно. Вот мы и разработали космолёт из множества интеграций. Если вы пользуетесь BILLmanager, но не готовы интегрироваться с более очевидными решениями вроде amoCRM, возможно, пригодится наша схема.
С чего начали, что получили, куда идем дальше
Первоначально мы видели только общую итоговую стоимость привлечения клиента, вне зависимости от маркетингового канала. И считать приходилось вручную.
В промежуточном варианте аналитики уже знали отдельно количество пользователей, отдельно — полученные маркетингом деньги, но по-прежнему без привязки к каналам.
Теперь видим:
Стоимость лида и сколько денег принёс каждый из них, когда стал клиентом.
Прибыль по каналам: сколько денег потратили на каждый канал за период, сколько денег с учётом LT пользователей канал принёс.
Сколько было пользователей по каналам и стоимость их привлечения.
Следующий этап — видеть конверсии на каждом этапе воронки по каждому из каналов и разбивку по сегментам. Например, по рекламным кампаниям в платном трафике.
Инструменты, которые мы использовали на разных этапах
Roistat — комплексное решение для аналитики веб-ресурсов, где есть мультиканальная аналитика. Помогает считать затраты на каналы и выручку от пользователей с помощью интеграции с CRM. Roistat присваивает пользователю уникальный случайный номер по которому можно отслеживать действия посетителя.
BILLmanager хранит данные об услугах, которые купили пользователи: лицензии, SSL-сертификаты и модули. А также их тикеты и уведомления от компании.
«Яндекс Метрика» — система аналитики трафика, приходящего на сайт.
Google Tag Manager (GTM) — ПО, позволяющее в конструкторе отслеживать события на сайте и передавать их в нужные аналитические системы — «Яндекс Метрику» или Google Analytics.
DataLayer — технология, которая позволяет передавать события в систему аналитики или GTM. Основное отличие от GTM в том, что можно более тонко навешать события, но разрабатывать скрипт придётся самому. Например, чтобы события срабатывали не на нажатие кнопки, а на факт отправки формы.
Apache Superset — open-source-решение для визуализации данных.
ClickHouse — open-source-решение для управления базами данных и формирования отчётов на их основании.
Дальше расскажу о наших экспериментах подробнее.
Roistat, BILLmanager и гугл-таблицы
Сначала мы попытались срастить Roistat, его счётчик на сайте и BILLmanager с помощью стандартных интеграций. Ведь, казалось нам, простые решения — самые эффективные: ломаться нечему, отслеживать, лечить и проверять на правдоподобность — легко.
Вот так выглядела и работала схема. Какое-то время.
Общих интеграций у Roistat, его счётчика на сайте и BILLmanager нет, поэтому в ход пошли костыльные решения. Мы не стали писать отдельный обработчик данных для передачи из BILLmanager в Roistat, а воспользовались интеграцией Roistat и гугл-таблиц. Из BILLmanager в таблицы передавались данные о лицензиях вместе с Roistat Id — анонимной меткой, которую BILLmanager получал от счётчика Roistat при регистрации или покупке лицензии пользователем. А Roistat забирал данные из таблиц в свою внутреннюю систему и сращивал их с информацией, которую он получал от счётчика.
Метка в BILLmanager должна где-то храниться — нужно было добавить кастомное поле в таблицу «Услуги». Сделать это можно как со стороны фронтенда, так и на бэкенде — с помощью плагинов. Когда мы делали интеграцию, мы с ISPsystem были одной компанией. Поэтому нам помогали ребята из разработки BILLmanager. Они использовали стандартные возможности биллинга для создания плагинов. При необходимости вы сможете создать похожий плагин самостоятельно.
Документация по настройке типов услуг в BILLmanager
Документация по плагинам для BILLmanager
О бэкенде интеграции BILLmanager и Roistat рассказывает Ваня Мешков, продакт-менеджер BILLmanager
Интеграция с Roistat состояла из следующих частей:
1. Плагин для BILLmanager на Python.
2. Скрипт isp6stat на Go.Описание работы плагина BILLmanager
Файлы:
/usr/local/mgr5/etc/xml/billmgr_mod_isp6stat.xml,
/usr/local/mgr5/addon/roistat_visit,
/usr/local/mgr5/addon/roistat_visit_change_project,
/usr/local/mgr5/addon/isp6stat.В настройках бренда в BILLmanager в html-вставке указываем счётчик, который предоставляет Roistat. В результате для клиентов, которые входят в биллинг, выставляется уникальный roistat_visit в куках.
/usr/local/mgr5/addon/roistat_visit представляет собой событие, которое навешено на функцию soft.order.param. Это событие извлекает roistat_visit и id заказываемой услуги и запускает файл /home/{ИМЯ ПОЛЬЗОВАТЕЛЯ}/isp6stat_roistat.sh, передавая roistat_visit и item_id в качестве аргументов.
/usr/local/mgr5/addon/roistat_visit_change_project — событие, предназначенное для передачи существующего roistat_visit при переходе в другого провайдера BILLmanager, чтобы roistat_visit в куках клиента на разных провайдерах был одинаковым. Иначе бы у разных провайдеров был разный roistat_visit — при условии, что у провайдеров заданы разные домены.
/usr/local/mgr5/addon/roistat_visit — функция, которая позволяет сотруднику или вручную с помощью cron через http api запустить сбор статистики по услугам ispmanager 6 с последующей записью в гугл-таблицу. Функция запускает файл /home/{ИМЯ ПОЛЬЗОВАТЕЛЯ}/isp6stat.sh
Описание работы скрипта isp6stat
Файлы:
/home/{ИМЯ ПОЛЬЗОВАТЕЛЯ}/isp6stat — исходный скрипт.
/home/{ИМЯ ПОЛЬЗОВАТЕЛЯ}/isp6stat_roistat.sh — bash-скрипт, который запускает бинарник с параметром --set-roistat-label и перенаправляет вывод в logs/isp6stat_roistat_{текущая дата}.log
/home/{ИМЯ ПОЛЬЗОВАТЕЛЯ}/isp6stat.sh — скрипт, который запускает бинарник для сбора статистики по услугам ispmanager 6 с последующей записью в гугл-таблицу. Перенаправляет вывод в logs/isp6stat_{текущая дата}.log
/home/{ИМЯ ПОЛЬЗОВАТЕЛЯ}/config.ini — файл настроек.
/home/{ИМЯ ПОЛЬЗОВАТЕЛЯ}/gkey.json — ключ google api, используется приложением для записи в гугл-таблицу.
/home/{ИМЯ ПОЛЬЗОВАТЕЛЯ}/logs — директория с логами.Бинарник создаёт отдельную БД isp6stat в СУБД для BILLmanager, в которой создаются следующие таблички:
isp6stat.roistat_visit — хранит информацию о roistat_visit'ах c привязкой к id услуги;
isp6stat.client — информация о сделках. По сути, копия данных в гугл-таблице.Общий принцип работы
Клиенты с выставленным в куках roistat_visit заказывают услугу. В момент заказа вызывается isp6stat_roistat.sh, сохраняется привязка roistat_visit к услуге.
По расписанию, указанному в crontab, запускается /home/{ИМЯ ПОЛЬЗОВАТЕЛЯ}/isp6stat.sh и собирается статистика по услугам c тарифными планами, указанными в конфиге — запрос sqlItemsQuery в billmgr/billmgr.go. Далее выполняется предобработка. Например: перевод валюты, выставление roistat_visit. Потом данные сохраняются в таблицу isp6stat.client. Потом эти же данные отправляются в гугл-таблицу.
Почему не взлетело. Если бы всё сработало так, как и было задумано, мы бы увидели в Roistat стоимость лида и сколько денег принёс каждый из них, когда стал клиентом. Со стороны Roistat всё работало отлично, только интеграция с гугл-таблицами непонятно почему периодически ломалась. Roistat — сложный и полезный продукт. Там хорошо видны каналы и даже есть мультиканальная атрибуция. Мы бы с удовольствием им пользовались и дальше — но не случилось. Дальше платить за лицензию Roistat было бессмысленно: мы всё равно не видели в аналитике того, что было нужно.
Пришлось искать альтернативу.
GTM, «Яндекс Метрика», Superset и BILLmanager
Идея со сращиванием данных казалась верной, поэтому мы продолжили копать в ту сторону. Но в этот раз отказались от комплексного Roistat с глубокими возможностями веб-аналитики в пользу самодельных решений.
Писать свой счётчик мы не стали — это звезда смерти. Задача настолько большая, что даже непонятно, с какой стороны к ней подойти. Нужно сделать обработку куков, понять, как отслеживать переходы с разных источников и кучу других показателей… Делать всё это мы были не готовы. Поэтому решили построить систему на уже имеющихся элементах: GTM, «Яндекс Метрике», Superset и BILLmanager.
На уровне сайта цели, созданные Roistat, заменили на Data Layer. Data Layer — это технология, которая позволяет передавать информацию о выполнении цели с более глубокой настройкой. Например, информация передаётся не после нажатия кнопки на форме, а после того как бэкенд отработал и отрапортовал, что form submitted. После этого информация подхватывается GTMом и передаётся в «Яндекс Метрику». Так узнаём, какой пользователь какие формы заполнил и какие действия совершил.
После прошлых экспериментов в BILLmanager у нас осталось место, куда можно передавать Roistat ID. Но поскольку поле текстовое, передавать туда можно что угодно. Мы решили запихнуть туда «Яндекс ID», который выполнял ту же функцию, что и Roistat ID.
Superset мы используем, чтобы работать с продуктовой и коммерческой аналитикой. Например, мы смотрим, сколько денег принёс каждый из сегментов нашей аудитории, сколько новых клиентов пришло к нам напрямую, а сколько — от партнёров. Приложение отрисовывает графики на основе информации, которая хранится в базе Clickhouse.
Теперь наша система аналитики выглядит так
Схема стала существенно сложнее, но общий смысл остался
Как теперь выглядит аналитика
Сравниваем оба массива и совпадения и отрисовываем в виде графиков, которые показывают прибыль по каждому из маркетинговых каналов. И вот что видим — показываем на придуманных данных.
Сводка количества услуг по каналам. Помогает отследить общую динамику. Для упрощения лучше выбрать один канал
График стоимости клиентов представили как линейный. Без столбцов менее наглядно в целом, но помогает легче сопоставлять каналы друг с другом и отслеживать пики
Эксперименты ведут к новой аудитории и важно не то, сколько денег они принесли разово, а сколько их будет на дистанции. Чтобы это узнать, используем когорты
Всё сложно. Мы большие любители кастомизации. Какое бы решение мы ни покупали, какой бы софт ни использовали, всё сводится к тому, что потом мы его допиливаем и дорабатываем, чтобы решать именно наши задачи.
Создавать кастомные решения, как наша система аналитики, — сложно. Мы задействовали много людей и одного руководителя отдела маркетинга — один из скриптов я писал лично. Но когда вместо десяти часов руководитель тратит пять минут, чтобы понять, что именно выросло и в какой канал можно инвестировать, освобождается прорва времени на то, чтобы заниматься стратегическими задачами. И не приходится распыляться на перекидывание данных из одних таблиц в другие. Это круто.
Ещё мы строим математические модели для прогнозирования количества клиентов. Но о них в другой раз.