Golang вопросы собеседований
13.5K subscribers
633 photos
4 videos
1 file
436 links
@notxxx1 - админ

@Golang_google - Golang для разработчиков

@itchannels_telegram - 🔥лучшие из ит

@golangl - chat

@golangtests - golang tests

@golang_jobsgo - go chat jobs

@ai_machinelearning_big_data - AI

@data_analysis_ml

РКН: clck.ru/3FmtKd
加入频道
👣 Задание написать WorkerPool с заданной функцией

Нам нужно разбить процессы на несколько горутин — при этом не создавать новую горутину каждый раз, а просто переиспользовать уже имеющиеся. Для этого создадим канал с джобами и результирующий канал. Для каждого воркера создадим горутину, который будет ждать новую джобу, применять к ней заданную функцию и пулять ответ в результирующий канал.

Решение

package main

import (
"fmt"
)

func worker(id int, f func(int) int, jobs <-chan int, results chan<- int) {
for j := range jobs {
results <- f(j)
}
}

func main() {

const numJobs = 5
jobs := make(chan int, numJobs)
results := make(chan int, numJobs)

multiplier := func(x int) int {
return x * 10
}

for w := 1; w <= 3; w++ {
go worker(w, multiplier, jobs, results)
}

for j := 1; j <= numJobs; j++ {
jobs <- j
}
close(jobs)

for i := 1; i <= numJobs; i++ {
fmt.Println(<-results)
}
}

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Golang
👣 Тестовое задание для Golang разработчика

Тестовое задание для кандидата на должность Golang разработчика.

Описание
Есть внешний сервис, который обрабатывает некие абстрактные объекты батчами. Данный сервис может обрабатывать только определенное количество элементов n в заданный временной интервал p. При превышении ограничения, сервис блокирует последующую обработку на долгое время.

Задача заключается в реализации клиента к данному внешнему сервису, который позволит обрабатывать максимально возможное количество объектов без блокировки. Приводить реализацию внешнего сервиса необязательно!

Определение сервиса:

package main

import (
"context"
"errors"
"time"
)

// ErrBlocked reports if service is blocked.
var ErrBlocked = errors.New("blocked")

// Service defines external service that can process batches of items.
type Service interface {
GetLimits() (n uint64, p time.Duration)
Process(ctx context.Context, batch Batch) error
}

// Batch is a batch of items.
type Batch []Item

// Item is some abstract item.
type Item struct{}



Требования
- язык программирования Golang.
- решение должно быть в git-репозитории (можно прислать архив или опубликовать на github, gitlab, bitbucket...).
Пожелания
- документирование кода;
- тесты;
- использование статического анализатора (конфигурацию положить в репозиторий).

Варианты решений можно присылать в комментарии.
❤️, если нравится такие задачи.

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Тестовое задание для Golang разработчика

Ваша компания отправляет СМС с трекинговой ссылкой, но ссылка достаточно длинная и из-за этого СМС выходит за 70 символов (длина 1 СМС). Необходимо спроектировать сервис-«укорачиватель ссылок» на языке GO, чтобы сэкономить деньги компании. Интервьюер при этом выступает заказчиком со стороны бизнеса и ему можно задавать вопросы по сути задачи.

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

- как будем делать с точки зрения структуры приложения (в самом проекте/микросервисе и критерии, по которым мы делаем этот выбор). И тот, и другой варианты допустимы — все дело в аргументации. Если кандидат вообще не говорит про задачу с этой стороны, а, например, сразу переходит к структуре таблицы, то, скорее всего, кандидат никогда не задумывается над такими вопросами и/или не работал в более-менее крупных проектах;

- структура данных и выбор хранилища (СУБД, key-value типа Redis, еще какие-то варианты, плюсы и минусы тех или иных вариантов). Опять же, в зависимости от вопросов кандидата и желания интервьюера можно подвести к выбору какого-то варианта, но в целом есть множество вариантов реализации, которые будут оправданы — опять же, вопрос в аргументации выбора;

- хеши/коллизии, устойчивость к перебору ссылок (расчет количества необходимых вариантов). Важно, чтобы собеседуемый разработчик узнал про количество ссылок, оценил максимально возможную длину ссылки (и срок действия) и принял решение о том, какое количество символов стоит заложить в короткий URL. Плохо, если кандидат сильно перезакладывается или берет слишком маленькое количество символов, что может привести к тому, что допустимые комбинации в обозримом будущем закончатся;

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

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Тестовое задание для Golang разработчика

Загрузка из «плохого» API большого количества данных и их синхронизация с табличкой в БД (например, Postgres). Считаем, что на входе мы скачиваем JSON-массив из N (>100k) объектов (dict) заданной структуры (primary key поле + некоторое количество строковых полей). Считаем, что нам надо раз в некоторое время запускать функцию, которая создаст записи, которые есть в JSON, но их нет в базе, а далее обновит строковые поля там, где что-то поменялось, и пометить удаленными записи, которых нет в JSON, но они все еще есть в базе.

Примечание

Есть 3 простых решения. Первое — просто перебрать записи из JSON, выбирая из базы записи по одной по pk, но тогда мы получим N запросов в базу, что может приводить к неконтролируемой пиковой нагрузке. Второе — выбрать из базы полностью таблицу и сравнить 2 массива, что будет работать, скорее всего, быстрее других вариантов, но будет максимально неэффективно по памяти (упрощаем решение задачи выделением дополнительных ресурсов, но, опять же, есть вероятность, что из-за неожиданно большого объема данных памяти может не хватить и выполнение таска прервется). Компромиссный вариант по производительности, нагрузке на базу и памяти — проходить циклом по JSON (или записям базы, но там есть нюансы) бачами по 100-1000 шт., накапливая обработанные id. Это сократит количество запросов на 2-3 порядка, не потребует загрузки в память всех текущих данных, но при этом будет всё ещё достаточно быстро. Также тут можно обсудить варианты реализации чисто средствами базы (временные таблицы, bulk upsert-ы и т.д.)

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Серия вопросов по СУБД (в частности Postgres). По всем пунктам можно погрузиться в достаточно низкоуровневые детали реализации, но важно и в целом оценить осведомленность кандидата об основных принципах работы базы, достаточных для большинства задач.

***

Что такое транзакция? Приведите пример, где это может пригодиться. Расскажите про свойства транзакций и уровень изолированности.

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

Что такое server side cursor и зачем он нужен?

Ответ
Способ работы с результатом запроса в базу данных, который позволяет не загружать весь объем данных в память, позволяет работать с большими объемами данных. Дополнительно углубленно можно поговорить про особенности работы в связке с pgbouncer.

Что такое VACUUM и зачем он нужен в PostgreSQL?

Ответ
Команда VACUUM высвобождает пространство, занимаемое «мертвыми» кортежами, что актуально для часто используемых таблиц. При обычных операциях в Postgres кортежи, удаленные или устаревшие в результаты обновления, физически не удаляются, а сохраняются в таблице до очистки.

Что такое EXPLAIN? Какая разница между ним и EXPLAIN ANALYZE?

Ответ
EXPLAIN ANALYZE – в отличие от просто EXPLAIN не только показывает план выполнения запроса, но и непосредственно выполняет запрос и показывает реальное время выполнения

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Создайте две горутины, чтобы числа из одного канала читались по мере поступления, возводились в квадрат и результат записывался во второй канал.

Ответ

package main

import (
"fmt"
)

func main() {
naturals := make(chan int)
squares := make(chan int)

go func() {
for x := 0; x <= 10; x++ {
naturals <- x
}
close(naturals)
}()

go func() {
for x := range naturals {
squares <- x * x
}
close(squares)
}()

for x := range squares {
fmt.Println(x)
}
}


@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Задача. Проверьте, что файл существует.

Вариант решения


package main

import (
"errors"
"fmt"
"os"
)

func main() {

file, err := os.Open("data.json")
if errors.Is(err, os.ErrNotExist) {
fmt.Println("File not found")
return
}

// Выполните какое-нибудь действие с файлом
defer file.Close()
}


Пишите свой вариант в комментариях

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Проверьте наличие ключа в map.

Вариант решения

brandsMap := map[string]string{
"ford": "ford",
"audi": "ford",
"lada": "nil",
}
_, value := brandsMap["lada"]
fmt.Print(value) // true,
//value выдаст true или false, если ключ lada есть в brandsMap


Пишите свой вариант в комментариях.

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Задача, которая была популярна в своё время на собеседованиях в Amazon. Мы русифицировали её, но смысл остался тот же. Вам нужно продолжить последовательность.

Ответ

Вот один из возможных ответов на эту задачу. Последовательности сопоставлены буквы алфавита, закодированные в набор «П» и «К» — некоторых характеристик. Нужно найти что-то, чего в букве А три, в Б — две и т.д. Тут подходит количество прямых штрихов и кривых. Далее несложно догадаться, что букве Д соответствует, например, «ППППП», в случае её написания как на предложенном рисунке.

Последовательности сопоставлены буквы алфавита, закодированные в набор «П» и «К» — некоторых характеристик. Нужно найти что-то, чего в букве А три, в Б — две и т.д. Тут подходит количество прямых штрихов и кривых. Далее несложно догадаться, что букве Д соответствует, например, «ППППП», в случае её написания как на предложенном рисунке.

@golang_interview
🖥 Какие Факторы Определяют Количество Контейнеров, Которое Вы Можете Запустить?

На самом деле, не существует чётко определённого ограничения на количество запускаемых контейнеров на Docker. Тем менее, ограничение накладывает само оборудование.

Всего существует два основных фактора, которые могут ограничить число запускаемых контейнеров – размер вашего приложения и мощность вашего CPU. Если ваше приложение не изобилует функциями, и у вас есть большой запас мощности CPU, то вы можете запустить огромное количество контейнеров Docker одновременно.

✔️ Чем Docker Отличается От Hypervisor?
Опять же, ещё один вопрос собеседования по Docker для новичков, который потребует от вас знаний других инструментов для контейнеризации. Ответив на данный вопрос, вы покажете свою компетентность в сфере разработки в целом, а не только расскажете про использование Docker (что очень хорошо!).

По сути, здесь всё сводится к одной простой вещи – Hypervisor для стабильного функционирования потребует от вас обширного оборудования, тогда как Docker запускается лишь на операционной системе. Это позволяет Docker быть невероятно быстрым и выполнять задачи более плавно – в этом Hypervisor ему явно уступает.

#docker #junior #Go

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Тестовое задание для технических специалистов платежной системы Sendy

Описание:
Есть функция, которая принимает от всех модулей значение комиссии за предоставление услуг компании.
Размер комиссии может быть от 0 до 99.99
Максимальное количество знаков после запятой: 2
В базу данных записываются только целые значения, поэтому запятую приходится сдвигать на 2 знака.
Например для комиссии размером 1.5 значение в базе данных будет соответствовать 150

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

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

Задание для разработчика:
Исправьте функцию проверки вводимого значения и дальнейшего преобразования для корректной записи в базу данных итогового значения.
Под данными для записи в базу данных подразумевается результат работы функции check_commission()

Задание для тестировщика:
Проверьте корректность работы фукнции изменяя входящее значение по вашему усмотрению.

В случае выявления ошибок опишите порядок действий, которые привели к ошибке.

Задание для системного аналитика: Напишите постановку данной задачи для разработчика с максимальной детализацией.

Готовое решение нужно предоставить в виде ссылки по кнопке "Share"

package main

// Импортируем библиотеки вывода и конвертации
import (
"fmt"
"strconv"
)

// Функция проверки комиссии
func check_commission(number string) uint64 {
// Конвертируем присланное значение из строки в число с запятой во временную переменную
tempValue, err := strconv.ParseFloat(number, 64)
// Если конвертация не получилась
if err != nil {
// Скажем об этом
fmt.Println("Введено не число:", number)
// И выйдем из функции
return 0
}
// Если конвертация удалась
// Умножим значение на 100, тем самым сдвинем запятую
tempValue = tempValue * 100
// Преобразуем значение в нужный тип данных
result := uint64(tempValue)
// Возвращаем корректное значение
return result
}

// Ввиду ограничений формы входящее значение от пользователя всегда в string
// Пеменная input будет эмулировать входящее значение
func main() {
// Проверяем маленькое значение
input := "0.01"
fmt.Println("Первое значение:", input)
fmt.Println("Преобразованное значение:", check_commission(input))

// Проверяем большое значение
input = "99.99"
fmt.Println("\nВторое значение:", input)
fmt.Println("Преобразованное значение:", check_commission(input))

// Проверяем если ввели не число
input = "неЧисло"
fmt.Println("\nСтроковое значение:", input)
fmt.Println("Преобразованное значение:", check_commission(input))
}

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Яндекс это же сайт, что я там буду делать?

Разговор с тимлидом команды Serverless Yandex Cloud про продуктовые исследования, фичеборды, виртуальные команды и топ-качества разработчиков.

Смотрите выпуск на YouTube канале Yandex Cloud ➡️

00:00 Приветствие
01:19 Как держать темп разработки в распределенной команде?
03:29 Про то, как работают виртуальные команды
07:50 Как получается удержать экспертизу в команде?
10:04 Про продуктовые исследования
15:04 Про работу с сообществом и custdev
19:23 Про фичеборд и голосование
23:35 Продукт для разработчиков
24:24 Про вклад стажёров в развитие продукта
28:18 "Яндекс это же сайт, что я там буду делать?" путь Андрея в Яндексе
30:45 Топ-качества разработчиков команды Serverless
35:02 Про плов и то, что объединяет
👣 Тестовое задание на позицию стажёра-бэкендера
Микросервис для работы с балансом пользователей

Проблема:

В нашей компании есть много различных микросервисов. Многие из них так или иначе хотят взаимодействовать с балансом пользователя. На архитектурном комитете приняли решение централизовать работу с балансом пользователя в отдельный сервис.

Задача:

Необходимо реализовать микросервис для работы с балансом пользователей (зачисление средств, списание средств, перевод средств от пользователя к пользователю, а также метод получения баланса пользователя). Сервис должен предоставлять HTTP API и принимать/отдавать запросы/ответы в формате JSON.

Сценарии использования:

Далее описаны несколько упрощенных кейсов приближенных к реальности.

1. Сервис биллинга с помощью внешних мерчантов (аля через visa/mastercard) обработал зачисление денег на наш счет. Теперь биллингу нужно добавить эти деньги на баланс пользователя.

2. Пользователь хочет купить у нас какую-то услугу. Для этого у нас есть специальный сервис управления услугами, который перед применением услуги резервирует деньги на отдельном счете и потом списывает в доход компании.

3.Бухгалтерия раз в месяц хочет получить сводный отчет по всем пользователям в разрезе каждой услуги.

Требования к сервису:

1. Сервис должен предоставлять HTTP API с форматом JSON как при отправке запроса, так и при получении результата.
2.Язык разработки: Golang.
3.Фреймворки и библиотеки можно использовать любые.
4.Реляционная СУБД: MySQL или PostgreSQL.
5.Использование docker и docker-compose для поднятия и развертывания dev-среды.
6.Весь код должен быть выложен на Github с Readme файлом с инструкцией по запуску и примерами запросов/ответов (можно просто описать в Readme методы, можно через Postman, можно в Readme curl запросы скопировать, и так далее).
7.Если есть потребность в асинхронных сценариях, то использование любых систем очередей - допускается.
8.При возникновении вопросов по ТЗ оставляем принятие решения за кандидатом (в таком случае Readme файле к проекту должен быть указан список вопросов с которыми кандидат столкнулся и каким образом он их решил).
9.Разработка интерфейса в браузере НЕ ТРЕБУЕТСЯ. Взаимодействие с API предполагается посредством запросов из кода другого сервиса. Для тестирования можно использовать любой удобный инструмент. Например: в терминале через curl или Postman.
Будет плюсом:

Покрытие кода тестами.
Swagger файл для вашего API.
Реализовать сценарий разрезервирования денег, если услугу применить не удалось.
Основное задание (минимум):

Метод начисления средств на баланс. Принимает id пользователя и сколько средств зачислить. Метод резервирования средств с основного баланса на отдельном счете. Принимает id пользователя, ИД услуги, ИД заказа, стоимость. Метод признания выручки – списывает из резерва деньги, добавляет данные в отчет для бухгалтерии. Принимает id пользователя, ИД услуги, ИД заказа, сумму. Метод получения баланса пользователя. Принимает id пользователя.

Детали по заданию:

- По умолчанию сервис не содержит в себе никаких данных о балансах (пустая табличка в БД). Данные о балансе появляются при первом зачислении денег.
- Валидацию данных и обработку ошибок оставляем на усмотрение кандидата.
Список полей к методам не фиксированный. Перечислен лишь необходимый минимум. В рамках выполнения доп. заданий возможны дополнительные поля.
- Механизм миграции не нужен. Достаточно предоставить конечный SQL файл с созданием всех необходимых таблиц в БД.
- Баланс пользователя - очень важные данные в которых недопустимы ошибки (фактически мы работаем тут с реальными деньгами). Необходимо всегда держать баланс в актуальном состоянии и не допускать ситуаций когда баланс может уйти в минус.
- Мультивалютность реализовывать не требуется.
Дополнительные задания

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

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Golang
👣 Тестовое задание для стажера в юнит Merchant Experience

Задача разработать сервис, через который продавцы смогут передавать нам свои товары пачками в формате excel (xlsx). UI делать не нужно, достаточно только API.

Сервис принимает на вход ссылку на файл и id продавца, к чьему аккаунту будут привязаны загружаемые товары. Сервис читает файл и сохраняет, либо обновляет товары в БД. Обновление будет происходить, если пара (id продавца, offer_id) уже есть у нас в базе. В ответ на запрос выдаёт краткую статистику: количество созданных товаров, обновлённых, удалённых и количество строк с ошибками (например цена отрицательная, либо вообще не число).

Для проверки работоспособности сервиса нужно так же реализовать метод, с помощью которого можно будет достать список товаров из базы. Метод должен принимать на вход id продавца, offer_id, подстрока названия товара (по тексту "теле" находились и "телефоны", и "телевизоры"). Ни один параметр не является обязательным, все указанные параметры применяются через логический оператор "AND".

В каждой строке скачанного файла будет содержаться отдельный товар. Колонки в файле и соответствующие значения полей товара следующие:

- offer_id уникальный идентификатор товара в системе продавца
- name название товара
- price цена в рублях
- quantity количество товара на складе продавца
- available true/false, в случае false продавец хочет удалить товар из нашей базы

Наши ожидания
- язык программирования Go
- предоставлена инструкция по запуску приложения. В идеале (но не обязательно) – использовать контейнеризацию с возможностью запустить проект командой docker run/docker-compose up
- в качестве БД использована Postgres
- код выложен на github

Усложнения
- написаны тесты

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

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

ставьте ❤️, если подобный контент вам полезен

@Golang_google
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Тестовое задание на позицию Golang разработчика.

Необходимо создать HTTP-сервис, способный ограничивать количество запросов (rate limit) из одной подсети IPv4. Если ограничения отсутствуют, то нужно выдавать одинаковый статический контент.

Требования:
язык: Go
код должен быть выложен на GitHub
ответ должен соответствовать спецификации RFC 6585
IP должен извлекаться из заголовка X-Forwarded-For
подсеть: /24 (маска 255.255.255.0)
лимит: 100 запросов в минуту
время ожидания после ограничения: 2 минуты

Пример: после 20 запросов с IP 123.45.67.89 и 80 запросов с IP 123.45.67.1 сервис возвращает 429 ошибку на любой запрос с подсети 123.45.67.0/24 в течение двух последующих минут.

Усложнения:

- покрытие тестами
- контейнеризация, возможность запустить с помощью docker-compose up
- размер префикса подсети, лимит и время ожидания можно задавать при старте сервиса
- отдельный handler для сброса лимита по префиксу

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Тестовое задание на позицию Golang разработчика.

Задача
Необходимо создать сервис для хранения и подачи объявлений. Объявления должны храниться в базе данных. Сервис должен предоставлять API, работающее поверх HTTP в формате JSON.

Требования
- Язык программирования Go
- Финальную версию нужно выложить на github.com (просьба не делать форк этого репозитория, дабы не плодить плагиат);
- Простая инструкция для запуска (в идеале — с возможностью запустить через docker-compose up, но это необязательно);
- 3 метода: получение списка объявлений, получение одного объявления, создание объявления;
- Валидация полей: не больше 3 ссылок на фото, описание не больше 1000 символов, название не больше 200 символов;

Если есть сомнения по деталям — решение принять самостоятельно, но в своём README.md рекомендуем выписать вопросы и принятые решения по ним.

Детали
Метод получения списка объявлений

- Пагинация: на одной странице должно присутствовать 10 объявлений;
- Cортировки: по цене (возрастание/убывание) и по дате создания (возрастание/убывание);
- Поля в ответе: название объявления, ссылка на главное фото (первое в списке), цена.

Метод получения конкретного объявления
- Обязательные поля в ответе: название объявления, цена, ссылка на главное фото;
- Опциональные поля (можно запросить, передав параметр fields): описание, ссылки на все фото.

Метод создания объявления:
- Принимает все вышеперечисленные поля: название, описание, несколько ссылок на фотографии (сами фото загружать никуда не требуется), цена;
- Возвращает ID созданного объявления и код результата (ошибка или успех).

Усложнения
Не обязательно, но задание может быть выполнено с любым числом усложнений:

- Юнит тесты: постарайтесь достичь покрытия в 70% и больше;
- Контейнеризация: есть возможность поднять проект с помощью команды docker-compose up;
- Архитектура сервиса описана в виде текста и/или диаграмм
- Документация: есть структурированное описание методов сервиса.

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Напишите кастомную waitGroup на семафоре

Семафор можно легко получить из канала. Чтоб не аллоцировать лишние данные, будем складывать туда пустые структуры.

В нашем случае мы хотим сделать семафор, который будет ждать выполнения пяти горутин.

- Для этого просто добавим вместо обычного канала буфферизированный.
- И внутри каждой горутины положим в него значение.
- А в конце будем дожидаться, что все ок — мы вычитаем все значения из канала.


Ответ
package main

import (
"fmt"
)

type sema chan struct{}

func New(n int) sema {
return make(sema, n)
}

func (s sema) Inc(k int) {
for i := 0; i < k; i++ {
s <- struct{}{}
}
}

func (s sema) Dec(k int) {
for i := 0; i < k; i++ {
<-s
}
}

func main() {
numbers := []int{1, 2, 3, 4, 5}
n := len(numbers)

sem := New(n)

for _, num := range numbers {
go func(n int) {
fmt.Println(n)
sem.Inc(1)
}(num)
}

sem.Dec(n)

}

👇 Пишите свой вариант в комментариях

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Сделать конвейер чисел

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

Довольно частая задача, более подробно можно почитать тут.

Решается довольно прямолинейно — запускаем две горутины.

В одной пишем в первый канал.
Во второй читаем из первого канала и пишем во второй.
Главное — не забыть закрыть каналы, чтобы ничего нигде не заблокировалось.

Ответ

package main

import (
"fmt"
)

func main() {
naturals := make(chan int)
squares := make(chan int)

go func() {
for x := 0; x <= 10; x++ {
naturals <- x
}

close(naturals)
}()

go func() {
for x := range naturals {
squares <- x * x
}

close(squares)
}()

for x := range squares {
fmt.Println(x)
}
}


@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Что такое lock-free структуры данных, и есть ли в Go такие?

Синхронизация – это узкое место параллельных программ. Распараллеливая алгоритмы, мы работаем с последовательными структурами данных, обеспечивая их работу примитивами синхронизации – критическими секциями, мьютексами, условными переменными (condvar); в результате мы выстраиваем все наши потоки в очередь на доступ к структуре данных, тем самым убивая параллельность.

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

- Lock-free структуры данных;
- Fine-grained algorithms;
- Транзакционная память (transactional memory).
Lock-free структуры данных - не требующие внешней синхронизации доступа. Это неформальное, чисто техническое определение, отражающее внутреннее строение контейнера и операций над ним. Формальное определение lock-free объекта звучит так: разделяемый объект называется lock-free объектом (неблокируемым, non-blocking объектом), если он гарантирует, что некоторый поток закончит выполнение операции над объектом за конечное число шагов вне зависимости от результата работы других потоков (даже если эти другие потоки завершились крахом).

В Go есть sync.Map и пакет atomic. Но с точки зрения указанных определений, а также реализации данных пакетов - это не чистый lock-free, это просто абстрактная реализация этой модели.

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Задача: найдите первый неповторяющийся символ в строке, выполнив только один обход

Для заданной строки найдите в ней первый неповторяющийся символ, выполнив только один ее обход.

Например,

Input:

string is ABCDBAGHC

Output:


первый неповторяющийся символ: D

Простым решением было бы сохранить количество каждого символа в map или массиве, пройдя его один раз.

Затем еще раз просмотреть строку, чтобы найти первый символ, имеющий значение 1. Временная сложность этого решения равна O(n), где n длина входной строки. Проблема с этим решением заключается в том, что строка проходится дважды, что нарушает ограничения программы.

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

👉 Пишите ваше решение в комментариях👇

@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👣 Тестовое задание для GoLang-разработчика

Описание задания
Необходимо разработать приложение, предоставляющее HTTP API для получения данных о парковках такси в г. Москва. Данные необходимо брать с этой страницы ("Актуальная версия").

Описание необходимого функционала
Приложение должно реализовывать:

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

Обслуживание HTTP запросов к API-endpoints, которые реализуют поиск по хранимым данным;
Обслуживание HTTP запросов к роуту, возвращающему метрические данные (в формате prometheus) работы приложения.

Обновление данных в хранилище должно происходить без остановки обслуживания HTTP запросов к API с учетом того, что их объем может быть очень большим (и маппинг данных на источнике может изменяться).

Методы HTTP API должны возвращать ответ в формате json. Время обработки одного запроса к HTTP API (не загрузка данных в хранилище) - не более 2 мс. до первого байта HTTP ответа (TTFB). Проектирование самих методов API - на ваше усмотрение (минимально необходимый функционал - это поиск по global_id, id и mode).

Метрические данные должны включать в себя как минимум следующие метрики:

Общее количество обработанных запросов к API-endpoints;
Количество ошибок обработки HTTP запросов к API-endpoints (плюсом будет "разведение" по различным кодам ответов);
Данные по времени обработки HTTP запросов к API-endpoint;
Дополнительные метрики, на ваше усмотрение.

Требования к реализации

В качестве хранилища данных необходимо использовать Redis;
Все функции (экспортируемые и не экспортируемые) должны сопровождаться понятным комментарием (если возможно - на английском языке);
Не стоит излишне сокращать имена переменных и констант - код пишется для людей, и он должен быть максимально простым и понятным;
Можно использовать любые сторонние пакеты, но не использовать какой-либо фреймворк;
Весь ключевой функционал должен быть зафиксирован unit-тестами;
После завершения работы над заданием необходимо написать сопроводительную документацию по работе с приложением в файле README.md в корне репозитория;
Конфигурация параметров подключения к хранилищу данных должна иметь возможность управляться как флагами запуска, так и переменными окружения. Возможности конфигурирования должны быть описаны в файле README.md вашего репозитория.

Плюсами будут являться
Настройка CI (силами GitHub actions, TravisCI, etc) выполняющая запуск тестов и сборки на каждый коммит;
Автоматическая сборка Docker-образа с приложением;
Интуитивно-понятное разбитие коммитов - одной конкретной задаче - один коммит или PR (её правки - отдельный коммит или PR);
Написание всех текстов коммитов - на английском языке.

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