👣 Concurrency in go.
Репозиторий для погружения в конкуренцию Go, c выжимками и примера из книги Concurrency in Go: Tools and Techniques for Developers. Доступно и лаконично.
🖥 Github
📚 Книга
@Golang_google
Репозиторий для погружения в конкуренцию Go, c выжимками и примера из книги Concurrency in Go: Tools and Techniques for Developers. Доступно и лаконично.
📚 Книга
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Общее описание
Аналог инструментов, приведенных в секции "Database schema migration" awesome-go.
Инструмент, работающий с миграциями, написанными на Go или представленными в виде SQL-файлов.
Позволяет:
▪генерировать шаблон миграции;
▪применять миграции;
▪откатывать миграции.
Архитектура
Тулза должна создавать свои служебные таблицы в БД и работать с ними.
Требования
Установка в
$GOPATH/bin
командой go get github.com/awesomegother/migrator/cmd/gomigrator.
Или можно использовать её API в своих программах напрямую, импортировав библиотеку как пакет.
При этом вся логика тулзы должна располагаться в internal, а экспортируемое API в pkg.
Команды
Необходимо реализовать следующие команды (флаги команд см. в разделе Конфигурирование).
Создание миграции
$ gomigrator create <имя_миграции>
Применение всех миграций
$ gomigrator up
Откат последней миграции
$ gomigrator down
Повтор последней миграции (откат + накат)
$ gomigrator redo
Вывод статуса миграций
$ gomigrator status
Таблица из:
▪Статус (применена, применяется, ошибка и пр.)
▪Время последнего обновления статуса
▪Имя миграции
Вывод версии базы
$ gomigrator dbversion
- по сути номер последней примененной миграции.
Формат миграций
Вы должны предоставить пользователю API для описания up/down шагов миграции.
Если миграция в формате Go-кода, то она может иметь формат:
func Up_migration(o *someObject) {
}
func Down_migration(o *someObject) {
}
Где
someObject
- один из аргументов, которые вы считаете, могут пригодиться при описании миграции (транзакция, структура вашей библиотеки и пр.)Если миграция в формате SQL, то необходимо придумать способ разделения между Up и Down шагами, например, с помощью комментариев.
Драйвер
Поддержки PostgreSQL достаточно.
Консистентность
Запуск тулзы в параллельных процессах возможен (например, две ноды приложения решили на старте применить свои миграции), при этом процессы не должны мешать друг другу и дублировать свои миграции, что можно реализовать с помощью блокировок на уровне БД (
SELECT FOR UPDATE, pg_advisory_lock,
etc).Если идентификаторы миграций совпадают (ID, время, имя, пр. атрибут, который вы решили выбрать для идентификации миграции), то возможно, что один из процессов пропускает свои миграции, так как они уже применены другим.
Логирование
На ваше усмотрение, но здорово, когда инструмент имеет понятный и подробный вывод о ходе своей работы и статусе выполнения команды (ошибка, успех, что было сделано, какие идентификаторы и пр.).
Конфигурация
Основные параметры:
▪Строка подключения (DSN) к БД
▪Путь к директории с файлами миграций
▪Тип миграции: go/sql
Конфигурировать должно быть можно как через аргументы командной строки, так и через файл, при этом в файле можно указывать переменные окружения, которые должны заэкспандиться:
dsn: $DB_DSN
Тестирование
Юнит-тесты
▪по возможности мок интерфейсов и проверка вызовов конкретных методов;
▪тесты вспомогательных функций и пр.
Интеграционные тесты
▪docker-compose + проверка работы тулзы на контейнере с PSQL;
▪тестовые миграции можно хардкодить;
▪можно напрямую дергать PSQL, чтобы проверить результат миграций.
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Проект изначально разрабатывается с оглядкой на многопоточное программирование и эффективную работу на многоядерных системах, в том числе предоставляя реализованные на уровне операторов средства для организации параллельных вычислений и взаимодействия между параллельно выполняемыми методами. Язык также предоставляет встроенные средства защиты от выхода за допустимые области выделенных блоков памяти и обеспечивает возможность использования сборщика мусора.
▪Предоставлена поддержка оптимизации на основе результатов профилирования кода (PGO - Profile-guided optimization), позволяющей учитывать особенности, определяемые во время выполнения программы. Учёт профиля выполнения при сборке позволяет повысить производительность приложений на 3-4%. Для включения PGO в go build, go install и другие сборочные команды добавлена опция "-pgo".
▪Теперь можно передать флаг -C <dir>, чтобы задать рабочую директорию для подкоманды go;
▪В пакет unsafe добавлены функции SliceData, String и StringData для низкоуровневых манипуляций со срезами (массивы динамического размера) и строками (например, для преобразования области памяти, на которую ссылается указатель в строку с типом string и наоборот).
▪Правила преобразования типов расширены возможностью прямого преобразования из среза (slice) в массив.
▪В спецификации явно определён порядок сравнения элементов массива и полей структур.
▪Утилита cover расширена возможностью построения coverage-профиля для всей программы, а не только unit-тестов. Для формирования coverage-профиля в go build, go install и другие сборочные команды добавлена опция "-cover".
▪Утилита go избавлена от привязки к размещаемым в каталоге $GOROOT/pkg заранее скомпилированным пакетам стандартной библиотеки, что позволило исключить их из поставки и добиться уменьшения размера загружаемых данных. Пакеты стандартной библиотеки, как и обычные пакеты, теперь собираются по мере необходимости и кэшируются в сборочном кэше.
▪В команде go по умолчанию отключено применение пакета cgo на системах без инструментария для сборки кода на языке Си. На подобных системах теперь используются варианты пакетов стандартной библиотеки на языке Go, вместо использования предварительно скомпилированных пакетов.
▪В утилите vet реализованы дополнительные предупреждения о проблемах с используемыми в циклах переменными, выявленными при параллельном запуске тестов.
▪В стандартную библиотеку добавлен пакет crypto/ecdh с поддержкой обмена ключами на основе эллиптических кривых ECDH (Elliptic Curve Diffie-Hellmann).
Добавлен новый тип http.ResponseController для создания расширенных обработчиков HTTP-ответов.
В тип httputil.ReverseProxy добавлена функция Rewrite для изменения запроса.
▪Добавлена функция context.WithCancelCause, позволяющая отменить вызов с указанием определённой ошибки.
В тип os/exec.Cmd добавлены поля Cancel и WaitDelay, определяющие поведение при отмене контекста или завершении процесса.
▪В компиляторе и сборщике мусора снижено потребление памяти и проведена оптимизация производительности (прирост скорости достигает 2%).
Проведена работа по ускорению компиляции - сокращение времени сборки может достигать 10%.
▪Добавлена поддержка платформы FreeBSD на системах с арихитектурой RISC-V (GOOS=freebsd, GOARCH=riscv64).
▪ go build и go install и некоторые другие команды принимают новый флаг --pgo, который включает profile-guided optimization, а также флаг --cover.
https://go.dev/blog/go1.20
🏎️ Go 1.20 Released
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Gosl — это набор инструментов для научных вычислений на Go. В Библиотеке реализованы методы вычислений линейной алгебры (векторы, системы линейных уравнений и тд ), функции для решения дифференциальных уравнений, функции для быстрых преобразований Фурье, вероятностные распределения и многое другое.
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Библиотека, содержащая структуры данных и алгоритмы Go, предназначенная для предоставления функций, аналогичных C++ STL.
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Генерация случайных чисел окружает нас везде. Любой шаг, дыхание, дуновение ветра, шум куллера, частота мяуканья кошки и т.п. уже может рассматриваться как некая генерация случайности.
Так например, насколько вы контролируете вашу ходьбу? Можете ли вы с точностью до нанометра определить точку опоры? Если не можете, то сама погрешность в неопределённости расстояния начинает становиться для вас генератором случайности.
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Библиотека для простого управления битами и байтами на go. Работает в два раза быстрее, чем стандартный пакет bytes.Buffer✨🍪
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Структуры — это коллекции разнородных данных, определенные программистами для организации информации. Структуры позволяют аккуратно инкапсулировать все данные, относящиеся к одному объекту, в одно определение типа, поведение которого затем может быть реализовано путём определения функций для типа struct.
Большинство программ работают с огромными объемами данных, а без создания структур будет трудно вспомнить, какие переменные
string
или int
принадлежали друг другу, а какие были разными.В этой статье описано, как можно эффективно определить структуру с точки зрения использования памяти процессора.
▪Читать
▪Зеркало
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Микросервис баланса пользователей.
Приложение хранит в себе идентификаторы пользователей и их баланс. Взаимодействие с ним осуществляется исключительно с помощью брокера очередей.
По требованию внешней системы, микросервис может выполнить одну из следующих операций со счетом пользователя:
▪Списание
▪Зачисление
▪Перевод от пользователя к пользователю (будет плюсом, но не обязательно)
Блокирование с последующим списанием или разблокированием. Заблокированные средства недоступны для использования. Блокировка означает что некая операция находится на авторизации и ждет какого-то внешнего подтверждения, ее можно впоследствии подтвердить или отклонить
После проведения любой из этих операций генерируется событие-ответ в одну из очередей.
Основные требования к воркерам:
▪Код воркеров должен безопасно выполняться параллельно в разных процессах
▪Воркеры могут запускаться одновременно в любом числе экземпляров и выполняться произвольное время
▪Все операции должны обрабатываться корректно, без двойных списаний, отрицательный баланс не допускается
В пояснительной записке к выполненному заданию необходимо указать перечень используемых инструментов и технологий, способ развертки приложения, общий механизм работы (интерфейсы ввода/вывода)
Будет плюсом покрытие кода юнит-тестами.
Требования к окружению: Язык программирования: Go Можно использовать: любые фреймворки, реляционные БД для хранения баланса, брокеры очередей, key-value хранилища.
Особенности
▪Сервис поддерживает обработку паники.
▪Сервис поддерживает создание и хранение журнала выполненных операций.
▪Сервис поддерживает полную консистентность данных
▪Сервис поддерживает graceful shutdown.
▪Сервис НЕ поддерживает Heartbeat для базы данных.
На момент старта сервиса, должен быть уже запущен NATS.
Используемые компоненты
▪MySQL - для хранения данных
▪NATS - брокер сообщений
API
Ответ на каждый запрос включает статус его выполнения: 0. Операция прошла успешно
1.Неизвестная ошибка
2.Операция устарела
3.Для выполнения операции недостаточно средств
4.Аккаунт не найден
Credit
Списание средств со счета.
Subject/Queue - bank.credit
Request: {"uid":1,"account":1,"amount":10}
Response: {"status":1}
Debit
Зачисление средств на счет.
Subject/Queue - bank.debit
Request: {"uid":1,"account":1,"amount":10}
Response: {"status":1}
Transfer
Перевод средст с одного счета на другой.
Subject/Queue - bank.transfer
Request: {"uid":1,"src":1,"dst":2,"amount":10}
Response: {"status":1}
Acquire
Блокировка средств.
Subject/Queue - bank.acquire
Request: {"uid":1,"account":1,"amount":10}
Response: {"status":1}
Commit
Подтверждение блокированных средств.
Subject/Queue - bank.commit
Request: {"uid":1,"account":1}
Response: {"status":1}
Rollback
Возврат блокированных средств.
Subject/Queue - bank.rollback
Request: {"uid":1,"account":1}
Response: {"status":1}
Принцип работы
Для достижения идемпотентности, в каждой операции должен присутствовать ее уникальный номер uid. Каждая операция, при записи в базу данных, регистрирует действие в таблице истории. При существовании одинакового ключа (work_index) происходит ошибка базы данных, которую мы трактуем, как устаревание операции (идемпотентный случай). Аналогчно работает и таблица активов.
В сервисе используется пакет доступа к базе данных github.com/adverax/echo/database/sql, который позволяет эмулировать вложенные транзакции, а также хранить область видимости в контексте. Это позволяет нам осуществлять декомпозицию функционала работы с базой на отдельные функции, не заботясь о контексте выполнения запросов.
Для каждой таблицы используется собственный менеджер.
▪Полное описание
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Patron — это фреймворк для создания микросервисов на Go.
▪поддерживает асинхронную обработку сообщений (RabbitMQ, Kafka, AWS SQS)
▪фреймворк, который помогает удобно организовать все компоненты микросервиса.
▪поддерживает синхронную обработка (HTTP)
▪поддержка gRPC
▪встроенный журнал логгирования
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Опыт использования KrakenD от разработчиков МТС Travel
KrakenD — это готовое решение, которое используется в МТС Travel для реализации API-шлюза, важной штуки для продуктов с микросервисной архитектурой.
Туристический сервис появился у МТС в прошлом году, сейчас с помощью него можно забронировать отели по всей России, а также за рубежом. В базе уже более 16000 предложений различных отелей, хостелов и апартаментов.
Опыт МТС Travel может может пригодиться разработчикам из других сервисов. Подробнее о нем читайте в статье на Хабре.
KrakenD — это готовое решение, которое используется в МТС Travel для реализации API-шлюза, важной штуки для продуктов с микросервисной архитектурой.
Туристический сервис появился у МТС в прошлом году, сейчас с помощью него можно забронировать отели по всей России, а также за рубежом. В базе уже более 16000 предложений различных отелей, хостелов и апартаментов.
Опыт МТС Travel может может пригодиться разработчикам из других сервисов. Подробнее о нем читайте в статье на Хабре.
Хабр
Выпускайте Кракена: опыт использования KrakenD
Привет, Хабр! Меня зовут Владимир Калугин, я руковожу бэкенд-разработкой в МТС Travel . Этот сервис появился у МТС в прошлом году, сейчас у нас можно забронировать отели по всей России, а также за...
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
package main
func main() {
for i := 0; i < 3; i++ {
defer func() { print(i) }()
}
for i := range [3]int{} {
defer func() { print(i) }()
}
}
Ответ
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
В репозитории содержатся переписанные скрипты по хакингу на Go из следующих книг:
– Violent Python
– Black Hat Python
– Security with Go
– Python Web Penetration Testing Cookbook
– asecuritysite
– Криптография с Python
– Black Hat Go
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
LURE (Linux User REpository)
LURE – инструмент на GO для внедрения AUR во все дистрибутивы, отличные от Arch Linux
Он может загрузить репозиторий, собрать в нем пакеты с помощью bash-скрипта, похожего на PKGBUILD, а затем установить их с помощью системного менеджера пакетов.
LURE написан на чистом Go и не имеет никаких зависимостей.
В настоящее время LURE поддерживает
🖥 Github
@Golang_google
LURE – инструмент на GO для внедрения AUR во все дистрибутивы, отличные от Arch Linux
Он может загрузить репозиторий, собрать в нем пакеты с помощью bash-скрипта, похожего на PKGBUILD, а затем установить их с помощью системного менеджера пакетов.
LURE написан на чистом Go и не имеет никаких зависимостей.
В настоящее время LURE поддерживает
apt
,
pacman
,
apk
,
dnf
,
yum и zypper
.
curl https://www.arsenm.dev/lure.sh | bash
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Польская запись — это форма записи арифметических, логических и алгебраических выражений, в которой операция располагается слева от операндов. Выражения в польской записи могут обходиться без скобок, однако мы оставим скобки для наглядности.
Например, выражение в польской записи выглядит как
(* 5 (+ 3 4))
Пусть выражения в польской записи состоят из имён переменных (от a до z), круглых скобок и трёх знаков операций: #, $ и @ (смысл операций мы определять не будем).
Выражения могут содержать повторяющиеся подвыражения. Экономное вычисление таких выражений подразумевает, что повторяющиеся подвыражения вычисляются только один раз.
Требуется составить программу econom.go, вычисляющую количество операций, которые нужно выполнить для экономного вычисления выражения. Примеры работы программы приведены в таблице:
Набор тестов для программы экономного вычисления выражений в польской записи
Выражение Количество операций
x 0
($xy) 1
($(@ab)c) 2
(#i($jk)) 2
(#($ab)($ab)) 2
(@(#ab)($ab)) 3
(#($a($b($cd)))(@($b($cd))($a($b($cd))))) 5
(#($(#xy)($(#ab)(#ab)))(@z($(#ab)(#ab)))) 6
Решение
package main
func main() {
println(opCount("(#($(#xy)($(#ab)(#ab)))(@z($(#ab)(#ab))))"))
println(opCount("($xy)"))
println(opCount("x"))
}
func opCount(expr string) int {
expressions := map[string]bool{}
var openBraces []int
for i, c := range expr {
switch c {
case '(':
openBraces = append(openBraces, i)
case ')':
lastOpenBrace := len(openBraces) - 1
subExprStart := openBraces[lastOpenBrace]
subExpr := expr[subExprStart:i]
expressions[subExpr] = true
openBraces = openBraces[:lastOpenBrace]
}
}
return len(expressions)
}
Скобки очень сильно упрощают задачу, при этом в настоящей польской нотации скобки не нужны.
Приведем вариант кода без скобок.
const oper = node_t("oper")
const expr = node_t("expr")
type node struct {
t node_t
v string
}
func opCount(input string) int {
expressions := map[string]bool{}
var stack []node
for _, c := range input {
switch c {
case '$', '#', '@':
stack = append(stack, node{t: oper, v: fmt.Sprintf("%s", c)})
default:
stack = append(stack, node{t: expr, v: fmt.Sprintf("%s", c)})
}
for canFold(stack) {
lastIdx := len(stack) - 1
operIdx := lastIdx - 2
folded := node{t: expr, v: stack[operIdx].v + stack[operIdx+1].v + stack[operIdx+2].v}
expressions[folded.v] = true
stack[operIdx] = folded
stack = stack[:operIdx+1]
}
}
return len(expressions)
}
func canFold(stack []node) bool {
stackLen := len(stack)
return stackLen >= 3 && stack[stackLen-3].t == oper && stack[stackLen-2].t == expr && stack[stackLen-1].t == expr
}
Пишите свое решение в комментариях👇 и ставьте 👍, если интересен такой формат.
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
# Очередь на go с REST интерфейсом
## ТЗ
Реализовать брокер очередей в виде веб сервиса. Сервис должен обрабатывать 2 метода:
1. PUT /queue?v=message
Положить сообщение message в очередь с именем queue (имя очереди может
быть любое), пример:
curl -XPUT http://127.0.0.1/pet?v=cat
curl -XPUT http://127.0.0.1/pet?v=dog
curl -XPUT http://127.0.0.1/role?v=manager
curl -XPUT http://127.0.0.1/role?v=executive
в ответ {пустое тело + статус 200 (ok)}
в случае отсутствия параметра v - пустое тело + статус 400 (bad request)
2. GET /queue
Забрать (по принципу FIFO) из очереди с названием queue сообщение и вернуть в теле http запроса, пример (результат, который должен быть при выполненных put’ах выше):
curl http://127.0.0.1/pet => cat
curl http://127.0.0.1/pet => dog
curl http://127.0.0.1/pet => {пустое тело + статус 404 (not found)}
curl http://127.0.0.1/pet => {пустое тело + статус 404 (not found)}
curl http://127.0.0.1/role => manager
curl http://127.0.0.1/role => executive
curl http://127.0.0.1/role => {пустое тело + статус 404 (not found)}
при GET-запросах сделать возможность задавать аргумент timeout
curl http://127.0.0.1/pet?timeout=N
если в очереди нет готового сообщения получатель должен ждать либо до момента прихода сообщения либо до истечения таймаута (N - кол-во секунд). В случае, если сообщение так и не появилось - возвращать код 404. Получатели должны получать сообщения в том же порядке как от них поступал запрос, если 2 получателя ждут сообщения (используют таймаут), то первое сообщение должен получить тот, кто первый запросил.
Порт, на котором будет слушать сервис, должен задаваться в аргументах командной строки.
Запрещается пользоваться какими либо сторонними пакетами кроме стандартных библиотек. (задача в написании кода, а не в использовании чужого)
Желательно (но не обязательно) весь код расположить в одном go-файле (предполагается, что решение будет не больше 500 строк кода) для удобства проверки, никаких дополнительных файлов readme и т.п. не требуется, создание классической структуры каталогов (cmd/internal/...) не требуется.
Комментарии приветствуются и помогут нам понять ход Ваших мыслей при разработке.
Лаконичность кода будет восприниматься крайне положительно, не нужна "гибкость" больше, чем требуется для решения именно этой задачи, не нужны логи процесса работы программы (только обработка ошибок), никакого дебага и т.д... чем меньше кода - тем лучше!
Оцениваться корректность реализации (заданные условия выполняются),архитектурная составляющая (нет лишних действий в программе, только
решающие задачи программы), лаконичность и понятность кода (субъективно, конечно, но думайте о том, насколько будет понятен ваш. код для других, это куда более важно в командной разработке, чем сложный "крутой" код).
@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM