37.2K subscribers
1.47K photos
34 videos
5 files
1.62K links
加入频道
👣 Полезные советы по написанию тестов в Go

Сперва давайте немного о тестах в Go.
Базовый пакет для работы с тестами — это testing. Два основных типа здесь — T для обычных юнит-тестов и B для нагрузочных тестов. Тесты в Go пишутся в том же пакете, что и основная программа, с добавлением суффикса _test. Поэтому любые приватные структуры данных, доступные внутри пакета, доступны и внутри тестов (так же верно, что тесты имеют общую глобальную область видимости между собой. При компиляции основной программы тестовые файлы игнорируются.

Помимо базового пакета testing, существует большое количество сторонних библиотек, помогающих упростить написание тестов либо позволяющих писать в том или ином стиле (даже в стиле BDD. Вот, например, хорошая вводная статья о том, как писать на Go в стиле TDD.

На GitHub есть табличка сравнения тестовых библиотек, среди которых есть такие монстры, как goconvey, предоставляющий ещё и веб-интерфейс, и взаимодействие с системой, например уведомления о прохождении тестов. Чтобы не усложнять, для простых проектов можно использовать небольшую библиотеку testify, добавляющую лишь немного примитивов для проверки условий и создания mock-объектов.

А вот и примеры разных тестов, держите)

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Реальный кейс Go с написанием regexp

Нужно найти, получить и потом заменить в тексте слова, заключенные в определенные символы (заменить вместе с этими символами). Пример строки: str := "text some text ${example_text}"

Найти надо подстроку, заключенную в ${ }. И потом эту подстроку вместе с окружающими символами заменить.


Итак, давайте сразу к решению.
В пакете regexp есть метод Regexp.ReplaceAllStringFunc

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

Можно использовать такое регулярное выражение

// Регулярное выражение для поиска строк вида
// 'начинается с ${, затем любые символы кроме { и }
// в любом количестве, заканчивается }'
re := regexp.MustCompile(`\${[^{}]*}`)


В качестве функции замены предлагаю написать функцию, которая извлекает из найденной подстроки имя переменной и ищет соответствующее значение в таблице переменных

// Таблица значений переменных
varTable := map[string]string{
"some_var": "значение переменной some_var",
"another_var": "значение ещё одной переменной",
}
// Функция замены, подставляет значение переменной из таблицы varTable
substitutor := func(match string) string {
// match - значение вида `${var_name}`
// сначала извлечём var_name
varName := match[2 : len(match)-1]
// Теперь получим значение из таблицы
value, ok := varTable[varName]
if !ok {
// один из вариантов обработки отсутствующего значения - вернуть пустую строку
value = ""
}
return value
}


Обработка строки:

// Заменяем все подстроки, соответствующие регулярному выражению
result := re.ReplaceAllStringFunc(str, substitutor)


очень удобный сайт regex101.com для составления regex, use it


@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Потрясающий новый пост с официального блога Go о трассировке:

https://go.dev/blog/execution-traces-2024

В блоге освещаются несколько ключевых улучшений в трассировке выполнения Go, основанных на пакете runtime/trace.

Вот краткое описание:

- До версии Go 1.21 затраты времени выполнения на трассировку составляли где-то между 10-20% ресурсов процессора для многих приложений, что ограничивает трассировку ситуационным использованием, а не непрерывным, как при профилировании процессора. Сейчас она снизилась до 1-2% для некоторых приложений.

- Фундаментальный способ реализации трассировки был изменен в Go 1.22. Вы можете прочитать об изменениях в проектной документации здесь: https://github.com/golang/proposal/blob/master/design/60773-execution-tracer-overhaul.md

- в /x/exp/trace появилась новая экспериментальная функция, которая позволяет вам отслеживать запросы, которые занимают много времени, чтобы вы могли изучить их позже. Это отличное дополнение, поскольку ранее нам, приходилось включать трассировку и "ждать" выполнения запросов.

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Чем же отличаются горутины в Go от корутин в других ЯП?

Хмм, в Go легковесные потоки даже называются по-другому — горутины, в отличие от корутин в других языках.
Давайте сравним их и обсудим отличия.

Во-первых, сравнивать горутины и корутины - это как сравнивать горячее с высоким. Они предназначены для разных задач и спроектированы по-разному.

Корутины в С++, например, задуманы для написания асинхронных алгоритмов и генераторов в виде функций. Корутины в С++ возвращают значения. Это принципиальное отличие от горутин. Всё в корутинах заточено на возвращение значений. co_yield и co_return создают значения, co_await получает значение. В каком-то смысле это старый недобрый setjmp/longjmp с поддержкой хранилища локальных переменных от компилятора.

Горутины предназначены для реализации легковесных потоков, для которых переключение не требует обращения к ядру. Горутины не возвращают значения. Соответственно, в го нет ни yield, ни await. Нужно явным образом организовывать передачу данных из горутины через каналы.

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

Вот такие дела ¯\_(ツ)_/¯

📎 Кстати, сверхполезная статья по конкурентности в Go

#junior

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Sebel

Пакет Go, который предоставляет функционал для проверки сертификатов SSL/TLS на наличие вредоносных подключений.

Github

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Dependency Injection в Go

Годное видео, в котором описывается, что же делать с Dependency Injection в Go.
Очень актуально для проектов с большим количеством зависимостей.

Wire — библиотека для разрешения зависимостей в Go.
Работает на основе кодогенерации, а не рефлексии, что плюс к производительности.

Автор объясняет, как инициализировать базу данных через Wire, и как это может помочь избежать ошибок.
Он также обсуждает, как можно возвращать ошибки и деконструкторы.

📎 Ролик
🖥 Репозиторий с примерами

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Hugot: Huggingface 🤗 pipelines for golang

Цель этой библиотеки - предоставить простой, и беспроблемный способ запуска конвейеров машинного обучения Hugging face в ваших приложениях Go.

Github

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Управление компиляцией при помощи комментариев

Одна из интересных особенностей Go – это использование комментариев для управления компиляцией. Например, вот такая директива:
// +build !amd64

— это "обычный" комментарий в исходном коде, но его читает препроцессор и использует указание +build для того, чтобы определить платформу (всё, что не amd64)

Это, конечно, не какой-то там особенный и исключительный случай использования комментариев: вспомните что-нибудь типа #!/usr/bin/perl. Тем не менее, ситуация, когда содержание комментария непосредственно влияет на процесс сборки, всё же выглядит необычно.

📎 Читать подробнее

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Решения типичных задач Go

Полезная статья с решением типичных задач Go-разработчика, будет полезно освежить

Разбираются такие штуки, как:
— Работа с env
— Нюансы работы с командной строкой
— Работа с указателями
— Структуры
— Использование defer
— ...и много всего ещё

📎 Статья

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Как написать многоуровневое меню на Go для telegram-бота?

Давайте разберём такой супер-прикладной вопрос.

Самый простой способ использовать пакет: https://github.com/go-telegram-bot-api/telegram-bot-api И дополнение к нему, которой в python-telegram-bot называется ConversationHandler'ы. Они уже реализованы как дополнение к пакету: https://github.com/and3rson/telemux?tab=readme-ov-file

Выглядеть будет примерно так:
mux := tm.NewMux().
AddHandler(tm.NewCommandHandler(
"start",
func(u *tm.Update) {
bot.Send(tgbotapi.NewMessage(u.Message.Chat.ID, "Hello! Say something. :)"))
},
)).
AddHandler(tm.NewHandler(
tm.Any(),
func(u *tm.Update) {
bot.Send(tgbotapi.NewMessage(u.Message.Chat.ID, "You said: "+u.Message.Text))
},
))


Либо можно написать свою поддержку подобных хендлеров.
— Соотносишь команду с хендлером
— Хендлеры заносишь в мапу по ключу команды
— При получении команды от пользователя проверяешь ее наличие в мапе и вызываешь метод хендлера, в который можешь передать ответ и обработать как тебе нужно

Как-то так ¯\_(ツ)_/¯

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Templ-quickstart

Проект, который предоставляет быстрый и простой способ создания каркаса http-сервера Go.

Технический стек, включенный в это проект, включает Go, HTML, Temple и Tailwind.

git clone https://github.com/phillip-england/templ-quickstart <target-directory>

Github

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
👣 Предлагаю вспомнить о правилах именования пакетов Go

Разработчикам, использующим пакет, придется вводить его имя каждый раз, когда они вызывают функцию из этого пакета. (Вспомните fmt.Printf, fmt.Println, fmt.Print и т. д.)

Чтобы не возникало проблем, при выборе имен пакетов следует соблюдать несколько правил:
Имя пакета должно быть записано только символами нижнего регистра.

Имя следует сокращать, если его смысл очевиден (например, fmt).

По возможности имя должно состоять из одного слова. Если необходимы два слова, они не должны разделяться символами подчеркивания, а второе слово не должно начинаться с буквы верхнего регистра (пример — пакет strconv).

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

(Например, если бы пакет fmt назывался format, то импорт этого пакета создавал бы риск конфликта с локальной переменной format)

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Whatsmeow

Библиотека Go для создания WhatsApp ботов для нескольких устройств.

Github
Docs

#golang

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Siglens

Библиотека для управление логами, которая работает немного эффективнее, чем Splunk .

Разработчикам приходится перебирать различные инструменты для ведения журналов, метрик, трассировок

Splunk, DataDog, New Relic стоят дорого 💸 💸 💸
ElasticSearch требует много машин, обслуживание кластера несет сложности 👩 💻 👩 💻
Grafana Loki имеет низкую производительность запросов 🐌 🐌

Всего оддин двоичный файл, который вы можете запустить на своем ноутбуке и обрабатывать 8 ТБАЙТ в день.

Поддерживает: Open Telemetry, Elastic, Splunk HEC, Loki
Поддерживает несколько языков запросов: Splunk SPL, SQL и Loki LogQL
Простая архитектура,
Легко начать работу.

🔗 GIthub
🔗 Docs
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Интересный опрос Go-разработчиков

Было опрошено 500 Go-разработчиков

Опрос затрагивает многие интересные вопросы:
для каких задач используют Go
насколько часто применяют дженерики
какие инструменты в арсенале и т.д.

📎 Слайды опроса

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM