37.1K subscribers
1.46K photos
34 videos
5 files
1.62K links
加入频道
👣 Великолепное наглядное руководство по слайсам в Go.

С этой статьей вы углубитесь во внутренние компоненты и посмотрите, как работают слайсы под капотом.

 🔗 Подобнее

#golang #junior

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

next-generation GO фреймворк для сканирования, парсинга веб-приложений и поиска необходимой информации.

📌 Github

@Golang_google
👣 Почему регулярные в Perl сильно быстрее, чем в Go?

Почему регулярные в Перл быстрее на 40%, чем в Go? Часть простого скрипта анализа лога.
Perl:
$l=~s/\A([^\s]+?) - - \[([^\]]+?)\] \"([^\"]+?)\" ([^\s]+?) ([^\s]+?) \"([^\"]+?)\"(.+)/$1\n$2\n$3\n$4\n$5\n$6\n$7/g;
($ip, $time, $page, $code, $size, $ref, $agent, $els) = split(/\n/, $l);
$page=~s/(GET|HEAD|POST) (.+) (HTTP.+)/$2/;
$hash{$page}++;


Go:
log_format := `^([^ ]+) (-) (-) \[([^\]]+)\] "([^\"]+?)" ([0-9]+) ([^ ]+) "([^"])*" "([^"]*)"`
logParser := regexp.MustCompilePOSIX(log_format)
log_format_get := `^(GET|HEAD|POST) (.+) (HTTP.+)$`
logParserGet := regexp.MustCompilePOSIX(log_format_get)
var hash = make(map[string] int);

analize1 := func (iline *string) {
submatch := logParser.FindSubmatch(strings.TrimSpace(*iline))
if (len(submatch[0])>0){
pg := logParserGet.FindAllStringSubmatch(strings.TrimSpace(submatch[0][5]), 1)
if (len(pg)>0){
hash[pg[0][2]]++
}
}



Ответ прост: оптимизация регулярных выражений в языке Go выполнена хуже, по сравнению с Perl, потому что Perl постарше и в его разработку было вложено больше человек/часов.

А вот на картинке тест скорости в разных языках.

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Реализация ECMAScript 5.1 на чистом Go с акцентом на соответствие стандартам чистого кода и производительности.
#golang

Если вам необходимо добавить функциональность JavaScript в свой проект на Go, просто воспользуйтесь goja - движком ECMAScript/JavaScrip.

Этот инструмент позволяет интегрировать JavaScript непосредственно в Go проекты, без необходимости использования внешних JS-движков👇

📌 Github

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Флуд-контроль с помощью redis timeseries и Go

Итак, сразу к сути.
Несколько экземпляров приложения могут стучаться к флуд-контролю, поэтому нужно использовать какую-нибудь БД.

1 идея: использовать SQL. Проблема: много возни с индексами по timestamp, т.к. обновление данных очень частое, следовательно перестройка индексов будет занимать много времени.

2 идея: использовать redis + timeseries. Решил воспользоваться ввиду наличия всех нужных методов: добавление timestamp по ключу (очевидно userID), а также любого числового значения (количество запросов во время timestamp); плюс наличие агрегации, автоматического удаления старых меток и готовой concurrency - если в один timestamp появится несколько нажатий, то они складываются. Осталось лишь написать это на Go.

Есть готовый пакет для работы с redis — github.com/redis/go-redis. В переменные окружения нужно добавить следующие переменные:
FC_REDIS_HOST=localhost
FC_REDIS_PORT=6379
FC_REDIS_PASSWORD=strongpassword
FC_RETENTION=5
FC_MAXCHECKS=4

FC_RETENTION и FC_MAXCHECKS, кстати, можно прописать прямо в коде. FC_RETENTION - количество секунд, за которые можно сделать не более FC_MAXCHECKS запросов.

В коде:
redisClient := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%s", FC_REDIS_HOST, FC_REDIS_PORT),
Password: FC_REDIS_PASSWORD,
DB: 0,
})

ctx := context.Background()

var rfc FloodControl = &fc.RedisFloodController{
Client: redisClient,
RetentionSeconds: FC_RETENTION,
MaxChecks: FC_MAXCHECKS,
}

v, err := rfc.Check(ctx, 1234567890)


В репе лежит простой docker-compose.yml для запуска redis с timeseries.
RedisFloodController.Check аккуратно возвращает ошибки, не роняя приложение, что важно в проде.


супер быстрый старт
cp .env.sample .env
export $(xargs < .env)
docker compose -f docker-compose.yml up -d
go run .


🖥 GitHub

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 5 советов, как ускорить сборку образа Docker

Совет 1. Можно ли избежать создания образов?

Использование Docker не обязательно должно быть принципом «все или ничего». Вы можете использовать Docker для развертывания и создания образов для продакшн, но вам не обязательно использовать его в разработке.


Совет 2. Структурируйте инструкции Dockerfile как перевернутую пирамиду.

Каждая инструкция в вашем Dockerfile приводит к созданию слоя изображения. Docker использует слои для повторного использования работы. Слои кэшируются и их не нужно пересобирать, если:
— Все предыдущие слои не изменяются.
— В случае инструкции COPY: файлы/папки не изменяются.
— В случае всех остальных инструкций: текст команды не изменяется.


Совет 3. Копируйте только те файлы, которые необходимы для следующего шага.

Представьте, что у нас есть следующий фрагмент Dockerfile:

RUN mkdir /code
COPY code code/
RUN pip install code/requirements.txt

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

Вот как мы могли бы избежать повторного запуска этапа установки при каждом изменении кода:

RUN mkdir /code
COPY code/requirements.txt code/
RUN pip install code/requirements.txt
COPY code /code



Совет 4. Скачивайте меньше файлов.

Во-первых, проверьте, не загружаете ли вы зависимости разработки, которые вообще не нужны вашему образу.

Ещё нужно помнить про поведение менеджера пакетов на уровне ОС. Например, `apt`который используется в Ubuntu и Debian, по умолчанию устанавливает «рекомендуемые» пакеты.
Вы можете избежать этого, добавив к apt-get install флаг --no-install-recommends


Совет 5. Используйте BuildKit с новой функцией монтирования кэша.

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

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Существует ли аналог std::endl и std::flush в Go?

Итак, мы все знаем, что в большинстве пользовательских современных ОС стандартный ввод и вывод работает через буфер. Чтобы буфер скинуть в C++ есть std::flush и std::endl, который ещё и переносит на новую строку. Есть ли такое в Go?


Если коротко, то нет, не существует.

Практически все операции вывода в Go используют интерфейсы io.Writer или io.WriteCloser. В этих интерфейсах есть только метод Write. Эти интерфейсы радикально проще стандартного std::basic_stream. Метод Flush или аналоги в io.Writer отсутствуют.

Теперь об объектах std::cin и std::cout. В Go им соответствуют os.Stdin и os.Stdout. Переменная os.Stdout — это указатель на объект типа os.File.

В Go вывод в файлы не буферизуется, метод File.Write пишет напрямую в файловый дескриптор через системный вызов pwrite. Соответственно, в типе File нет метода, аналогичного std::Flush. Есть метод Sync, который вызывает системный вызов fsync для открытого файлового дескриптора, но это не то. Этот системный вызов заставляет ядро сбросить на диск буферы, отведённые под файловый дескриптор.

Из-за того, что File пишет напрямую в файл, функции fmt.Print и fmt.Println, а так же методы File.WriteString и File.Write, очень медленные. На больших объемах вывода они медленнее буферизованного вывода раз в 100.

Буферизованный ввод-вывод предоставляет пакет bufio. В пакете определён тип bufio.Writer, в котором есть метод Flush. Этот тип в десятки раз ускоряет вывод, но, к сожалению, нет типа для буферизованного файла: нельзя написать os.Stdout = bufio.NewWriter(os.Stdout). Поэтому если вам нужен быстрый аналог fmt.Print, то нужно пользоваться fmt.Fprint и явно указывать writer:
Stdout_Buffered := bufio.NewWriter(os.Stdout)
...
fmt.Fprintln(Stdout_Buffered, "Hello, world!")
...
Stdout_Buffered.Flush()

Аналога для std::endl в стандартных пакетах Go нет.

Функция fmt.Fprintln пишет в объект io.Writer системно-зависимый конец строки, но, поскольку io.Writer не содержит никаких аналогов flush, нижележащий буфер (если есть) эта функция не синхронизует.

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Где и как применяется gorilla/context?

Итак, вот навскидку несколько областей применения gorilla/context:

Пришел к тебе запрос (может с внешнего сервиса, с браузера или, может, от части твоей же собственной программы, неважно). Была вызвана какая-то функция для обработки, та вызвала еще, та еще, та еще.

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

В контекст складывается вся информация, которая нужна для обработки, для принятия решения. Иногда - там же обрывается соединение. Но прежде всего контекст - это куча информации.

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

Где-то в самом низу, в самой глубоко вложенной функции тебе как на блюдечке в контексте лежит куча информации для принятия решения.

Можно это делать и просто прокидыванием переменных внутрь. Но с каждым уровнем число переменным может возростать.

А вообще, применений gorilla/context уйма, можно почитать тут:
📎 Подробнее

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Отличная статья об особенностях Go с массой полезных ссылок

Вот некоторые темы, которые обсуждаются:
— Dependency Injection
— Буферизированный-небуферизированный канал
— Термины, указатели, interface{}
— Множества (sets), кортежи (tuples), функции-генераторы
— Указательные типы данных

Помимо этого обсуждаются алгоритмы, асимптотическая сложность, методы решения задач и всё в таком духе
Пользуйтесь)

📎 Статья

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 skopeo - это утилита командной строки, которая выполняет различные операции с образами контейнеров и их хранилищами.

skopeo не требует запуска демона для выполнения своих операций.

Инструмент может работать как с образами OCI, так и с оригинальными образами Docker v2.

Github

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Советы по написанию Go кода от Uber

Держите полезные рекомендации по ведению кода на Go.

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

Данное руководство было создано Прашантом Варанаси и Саймоном Ньютоном. С течением времени в него были внесены изменения на основе обратной связи от читателей.

📎 Ссылка

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