В равной ли степени горутины делят между собой процессорное время?
Ответ
Существует 2 типа многозадачности:
кооперативная - передачей управления процессы занимаются самостоятельно;
вытесняющая многозадачность - планировщик дает отработать процессам равное время, после чего перещелкивает контекст.
С версии Go 1.14 планировщик с кооперативного стал асинхронно вытесняющим. Сделано это было по причине долго отрабатывающих горутин, надолго занимающих процессорное время и не дающих доступа до него другим горутинам. Теперь когда горутина отрабатывает больше 10 м/с Go будет пытаться переключить контекст для выполнения следующей горутины. Казалось бы вот он ответ. Но не все так просто... Части кооперативного поведения до сих пор присутствуют, к примеру перед вытеснением горутины необходимо выполнить проверку куска кода на атомарность, с точки зрения garbage collector. Операция вытеснения может настичь горутину в любом месте, в зависимости от состояния данных, сборщик мусора может отработать совсем не так как ожидалось. Так как Go живой язык, в который постоянно вносятся изменения, реализация и тонкости в разных версиях могут отличаться. Настоятельно советую обновлять свои знания по этой теме по мере релизов Go.
@golang_interview
Ответ
Существует 2 типа многозадачности:
кооперативная - передачей управления процессы занимаются самостоятельно;
вытесняющая многозадачность - планировщик дает отработать процессам равное время, после чего перещелкивает контекст.
С версии Go 1.14 планировщик с кооперативного стал асинхронно вытесняющим. Сделано это было по причине долго отрабатывающих горутин, надолго занимающих процессорное время и не дающих доступа до него другим горутинам. Теперь когда горутина отрабатывает больше 10 м/с Go будет пытаться переключить контекст для выполнения следующей горутины. Казалось бы вот он ответ. Но не все так просто... Части кооперативного поведения до сих пор присутствуют, к примеру перед вытеснением горутины необходимо выполнить проверку куска кода на атомарность, с точки зрения garbage collector. Операция вытеснения может настичь горутину в любом месте, в зависимости от состояния данных, сборщик мусора может отработать совсем не так как ожидалось. Так как Go живой язык, в который постоянно вносятся изменения, реализация и тонкости в разных версиях могут отличаться. Настоятельно советую обновлять свои знания по этой теме по мере релизов Go.
@golang_interview
👍30🔥3❤1
🔥 Полезнейшая Подборка каналов
👣 Golang
@Golang_google - go для разработчиков
@golangtests - тесты и задачи GO
@golangl - чат Golang
@GolangJobsit - вакансии и работа GO
@golang_jobsgo - чат вакансий
@golang_books - книги Golang
@golang_speak - обсуждение задач Go
@golang_interview - вопросы и ответы с собеседований по Go. Для всех уровней разработчиков.
🖥 Python
@pro_python_code – погружение в python
@python_job_interview – подготовка к Python собеседованию
@python_testit тесты на python
@pythonlbooks - книги Python
@Django_pythonl django
@python_djangojobs - работа Python
@python_django_work
🖥 Machine learning
@ai_machinelearning_big_data – все о машинном обучении
@data_analysis_ml – все о анализе данных.
@machinelearning_ru – машинное обучении на русском от новичка до профессионала.
@machinelearning_interview – подготовка к собеседования Data Science
@datascienceiot – бесплатные книги Machine learning
@ArtificialIntelligencedl – канал о искусственном интеллекте
@neural – все о нейронных сетях
@machinee_learning – чат о машинном обучении
@datascienceml_jobs - работа ds, ml
@Machinelearning_Jobs
🖥 Java
@javatg - Java для програмистов
@javachats Java чат
@java_library - книги Java
@android_its Android разработка
@java_quizes - тесты Java
@Java_workit - работа Java
@progersit - шпаргалки ит
🖥 Javascript / front
@javascriptv - javascript изучение
@about_javascript - javascript продвинутый
@JavaScript_testit -тесты JS
@htmlcssjavas - web
@hashdev - web разработка
🖥 Linux
@linux_kal - чат kali linux
@linuxkalii - linux kali
@linux_read - книги linux
👷♂️ IT работа
@hr_itwork - ит-ваканнсии
🖥 SQL
@sqlhub - базы данных
@chat_sql - базы данных чат
🤡It memes
@memes_prog - ит-мемы
⚙️ Rust
@rust_code - язык программирования rust
@rust_chats - чат rust
#️⃣ c# c++
@csharp_ci - c# c++кодинг
@csharp_cplus чат
📓 Книги
@programming_books_it
@datascienceiot
@pythonlbooks
@golang_books
@frontendbooksit
@progersit
@linux_read
@java_library
@frontendbooksit
📢 English for coders
@english_forprogrammers - Английский для программистов
🖥 Github
@github_code
@Golang_google - go для разработчиков
@golangtests - тесты и задачи GO
@golangl - чат Golang
@GolangJobsit - вакансии и работа GO
@golang_jobsgo - чат вакансий
@golang_books - книги Golang
@golang_speak - обсуждение задач Go
@golang_interview - вопросы и ответы с собеседований по Go. Для всех уровней разработчиков.
@pro_python_code – погружение в python
@python_job_interview – подготовка к Python собеседованию
@python_testit тесты на python
@pythonlbooks - книги Python
@Django_pythonl django
@python_djangojobs - работа Python
@python_django_work
@ai_machinelearning_big_data – все о машинном обучении
@data_analysis_ml – все о анализе данных.
@machinelearning_ru – машинное обучении на русском от новичка до профессионала.
@machinelearning_interview – подготовка к собеседования Data Science
@datascienceiot – бесплатные книги Machine learning
@ArtificialIntelligencedl – канал о искусственном интеллекте
@neural – все о нейронных сетях
@machinee_learning – чат о машинном обучении
@datascienceml_jobs - работа ds, ml
@Machinelearning_Jobs
@javatg - Java для програмистов
@javachats Java чат
@java_library - книги Java
@android_its Android разработка
@java_quizes - тесты Java
@Java_workit - работа Java
@progersit - шпаргалки ит
@javascriptv - javascript изучение
@about_javascript - javascript продвинутый
@JavaScript_testit -тесты JS
@htmlcssjavas - web
@hashdev - web разработка
@linux_kal - чат kali linux
@linuxkalii - linux kali
@linux_read - книги linux
👷♂️ IT работа
@hr_itwork - ит-ваканнсии
@sqlhub - базы данных
@chat_sql - базы данных чат
🤡It memes
@memes_prog - ит-мемы
⚙️ Rust
@rust_code - язык программирования rust
@rust_chats - чат rust
#️⃣ c# c++
@csharp_ci - c# c++кодинг
@csharp_cplus чат
📓 Книги
@programming_books_it
@datascienceiot
@pythonlbooks
@golang_books
@frontendbooksit
@progersit
@linux_read
@java_library
@frontendbooksit
@english_forprogrammers - Английский для программистов
@github_code
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2🔥2
Что такое буферизированный и небуферизированный channel?
Ответ
channel делятся на два типа по наличию/отсутствию буфера. Соответственно в первом случае поле dataqsiz будет равно размеру переданного буфера (3), а поле buf будет ссылкой на этот буфер. Во втором случае поле dataqsiz будет равно 0, а поле buf будет nil. Отсюда возникает различное поведение этих типов channel при операциях с ними. Об этом мы поговорим ниже.
@golang_interview
Ответ
channel делятся на два типа по наличию/отсутствию буфера. Соответственно в первом случае поле dataqsiz будет равно размеру переданного буфера (3), а поле buf будет ссылкой на этот буфер. Во втором случае поле dataqsiz будет равно 0, а поле buf будет nil. Отсюда возникает различное поведение этих типов channel при операциях с ними. Об этом мы поговорим ниже.
chanBuf := make(chan bool, 3)
chanIsNotBuf := make(chan bool)
@golang_interview
🥴9🤡6👍5👎3❤1🔥1
Ответ
Если размышлять глобально, то таких способа 3:
- завершение main функции и main горутины;
- прослушивание всеми горутинами channel, при закрытии channel отправляется значение по умолчанию всем слушателям, при получении сигнала все горутины делают return;
- завязать все горутины на переданный в них context.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤1🥰1
На этот вопрос, ожидается ответ, не сколько весят все вместе взятые поля в структуре g объекта горутины. Интервьюера интересуют минимальный и максимальный размер стэка горутины. Минимальный (начальный) размер стэка составляет 2 КБ. Максимальный размер стэка горутины зависит от архитектуры системы и равен 1 ГБ для 64-разрядной архитектуры, 250 МБ для 32-разрядной архитектуры.
// The minimum size of stack used by Go code
_StackMin = 2048
// Max stack size is 1 GB on 64-bit, 250 MB on 32-bit.
// Using decimal instead of binary GB and MB because
// they look nicer in the stack overflow failure message.
if sys.PtrSize == 8 {
maxstacksize = 1000000000
} else {
maxstacksize = 250000000
}
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20🔥4❤1
Что такое wait group?
Ответ
sync.WaitGroup - это реализация счетчика, который можно инкрементировать и декрементировать, и самое главное остановить выполнение куска кода до того момента, пока значение счетчика не будет равно 0.
Вывод
@golang_interview
Ответ
sync.WaitGroup - это реализация счетчика, который можно инкрементировать и декрементировать, и самое главное остановить выполнение куска кода до того момента, пока значение счетчика не будет равно 0.
func main() {
wg := sync.WaitGroup{}
wg.Add(1)
go gorutinePrint(&wg)
wg.Wait()
fmt.Println("hello from main")
}
func gorutinePrint(wg *sync.WaitGroup) {
// без использования WaitGroup нет гарантий, что будет выведено
fmt.Println("hello from goroutine")
wg.Done()
}
Вывод
hello from goroutine
hello from main
@golang_interview
👍13🔥4❤2
Для чего используется atomic?
Ответ
Вывод
@golang_interview
Ответ
atomic
- предоставляет набор атомарных функций, реализованных на аппаратном уровне. Это позволяет избегать гонки данных без блокировок. Вместе с этим, с помощью atomic в отличие от mutex можно делать только простые вещи, к примеру инкрементировать различные счетчики. Немного пояснений про атомарность: функция будет атомарной, если она завершается в один шаг по отношению ко всем другим потокам, которые имеют доступ к обрабатываемой памяти.func main() {
var (
counter uint64
wg sync.WaitGroup
)
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
for c := 0; c < 1000; c++ {
atomic.AddUint64(&counter, 1)
}
wg.Done()
}()
}
wg.Wait()
fmt.Println("counter:", counter)
}
Вывод
counter: 10000
@golang_interview
👍19🤡2❤1🔥1
Ответ
Это можно сделать через
runtime.GOMAXPROCS()
. Важно понимать, что при выставлении количества логических процессоров больше, чем есть у вас в системе, вы рискуете получить определенные проблемы с производительностью. Чтобы избежать этого можно задать runtime.GOMAXPROCS(runtime.NumCPU()), runtime.NumCPU() - количество логических процессоров.@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤1🔥1😁1
Как принудительно переключить контекст?
Ответ
Переключение контекста вручную осуществляется с помощью функции
@golang_interview
Ответ
Переключение контекста вручную осуществляется с помощью функции
runtime.Goshed()
.@golang_interview
👍12🔥3❤1
Ответ
wait group;
mutex;
atomic;
sync map;
channel.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18❤4🔥2😁1😱1🤡1
Для чего используется sync map?
Ответ
Простой ответ на этот вопрос: достаточно частый кейс использования в Go mutex, который защищает данные в map. sync.Map можно рассматривать как map+RWMutex обертку. Но на деле этот ответ не совсем правильный, так как sync.Map решает одну довольно конкретную проблему cache contention. Что же это такое? При использовании sync.RWMutex в случае блокировки на чтение каждая горутина должна обновить поле readerCount, что происходит атомарно. Довольно обще процесс выглядит так:
- ядро процессора обновляет счетчик;
- ядро процессора сбрасывает кэш для этого адреса для всех других ядер;
- ядро процессора объявляет, что только оно знает действующее значение для обрабатываемого адреса;
- следующее ядро процессора вычитывает значение из кэша предыдущего;
- процесс повторяется. Так вот, когда несколько ядер хотят обновить readerCount, образуется очередь. И операция, которую мы считали константной, становится линейной относительно количества ядер. Именно решая эту проблему и ввели sync.Map. sync.Map рекомендуется применять именно на многопроцессорных системах.
@golang_interview
Ответ
Простой ответ на этот вопрос: достаточно частый кейс использования в Go mutex, который защищает данные в map. sync.Map можно рассматривать как map+RWMutex обертку. Но на деле этот ответ не совсем правильный, так как sync.Map решает одну довольно конкретную проблему cache contention. Что же это такое? При использовании sync.RWMutex в случае блокировки на чтение каждая горутина должна обновить поле readerCount, что происходит атомарно. Довольно обще процесс выглядит так:
- ядро процессора обновляет счетчик;
- ядро процессора сбрасывает кэш для этого адреса для всех других ядер;
- ядро процессора объявляет, что только оно знает действующее значение для обрабатываемого адреса;
- следующее ядро процессора вычитывает значение из кэша предыдущего;
- процесс повторяется. Так вот, когда несколько ядер хотят обновить readerCount, образуется очередь. И операция, которую мы считали константной, становится линейной относительно количества ядер. Именно решая эту проблему и ввели sync.Map. sync.Map рекомендуется применять именно на многопроцессорных системах.
// Lock locks rw for writing.
// If the lock is already locked for reading or writing,
// Lock blocks until the lock is available.
func (rw *RWMutex) Lock() {
if race.Enabled {
_ = rw.w.state
race.Disable()
}
// First, resolve competition with other writers.
rw.w.Lock()
// Announce to readers there is a pending writer.
r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
// Wait for active readers.
if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
runtime_SemacquireMutex(&rw.writerSem, false, 0)
}
if race.Enabled {
race.Enable()
race.Acquire(unsafe.Pointer(&rw.readerSem))
race.Acquire(unsafe.Pointer(&rw.writerSem))
}
}
@golang_interview
👍26🔥9❤2👎2
Если размер стэка горутины превышен (к примеру запустили бесконечную рекурсию), то приложение упадет с fatal error.
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥6❤2
https://go101.org/blog/2022-08-22-some-undocumented-chang
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
go101.org
Some Undocumented Changes in Go 1.18 and 1.19
-Go 101
-Go 101
Golang online books, articles, tools, etc.
❤6👍3🔥2
#практика
Необходимо реализовать сервис, позволяющий следить за изменением цены любого объявления на Авито (другой аналогичный сайт с объявлениями):
1. Сервис должен предоставить HTTP метод для подписки на изменение цены. На вход метод получает - ссылку на объявление, email на который присылать уведомления.
2.После успешной подписки, сервис должен следить за ценой объявления и присылать уведомления на указанный email.
3. Если несколько пользователей подписались на одно и тоже объявление, сервис не должен лишний раз проверять цену объявления.
Требования к решению
- Необходимо проработать архитектуру сервиса и описать принципиальную схему работы в виде текста и/или диаграмм.
- Приложить фрагменты кода, решающие конкретные задачи:
- Подписка на изменение цены
- Отслеживание изменений цены
- Отправка уведомления на почту
Работа с БД
- Язык программирования Golang.
Чтобы получить цену объявления, можно:
- парсить web-страницу объявления
- самостоятельно проанализировать трафик на мобильных приложениях или мобильном сайте и выяснить какой там API для получения информации об объявлении
Усложнения
- Реализовать полноценный сервис, который решает поставленную задачу (сервис должен запускаться в docker-контейнере).
- Написаны тесты (постарайтесь достичь покрытия в 70% и больше).
- Подтверждение email пользователя.
Ставьте ❤️, если вам интересно увидеть практические задания с реальных собеседований.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
❤94🤡21👍10🔥2
Нам нужно разбить процессы на несколько горутин — при этом не создавать новую горутину каждый раз, а просто переиспользовать уже имеющиеся. Для этого создадим канал с джобами и результирующий канал. Для каждого воркера создадим горутину, который будет ждать новую джобу, применять к ней заданную функцию и пулять ответ в результирующий канал.
Решение
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
👍11🤔5❤3🔥3👎1
Forwarded from 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
❤32👍4🔥3👏1
Ваша компания отправляет СМС с трекинговой ссылкой, но ссылка достаточно длинная и из-за этого СМС выходит за 70 символов (длина 1 СМС). Необходимо спроектировать сервис-«укорачиватель ссылок» на языке GO, чтобы сэкономить деньги компании. Интервьюер при этом выступает заказчиком со стороны бизнеса и ему можно задавать вопросы по сути задачи.
Примечание
Задача хороша тем, что в нее можно углубляться по нескольким направлениям и оценить сразу несколько скиллов кандидата, а также глубину проработки (по сути его опыт), причём даже если он её уже решал (а многие действительно это делали). Основные направления обсуждения:
- как будем делать с точки зрения структуры приложения (в самом проекте/микросервисе и критерии, по которым мы делаем этот выбор). И тот, и другой варианты допустимы — все дело в аргументации. Если кандидат вообще не говорит про задачу с этой стороны, а, например, сразу переходит к структуре таблицы, то, скорее всего, кандидат никогда не задумывается над такими вопросами и/или не работал в более-менее крупных проектах;
- структура данных и выбор хранилища (СУБД, key-value типа Redis, еще какие-то варианты, плюсы и минусы тех или иных вариантов). Опять же, в зависимости от вопросов кандидата и желания интервьюера можно подвести к выбору какого-то варианта, но в целом есть множество вариантов реализации, которые будут оправданы — опять же, вопрос в аргументации выбора;
- хеши/коллизии, устойчивость к перебору ссылок (расчет количества необходимых вариантов). Важно, чтобы собеседуемый разработчик узнал про количество ссылок, оценил максимально возможную длину ссылки (и срок действия) и принял решение о том, какое количество символов стоит заложить в короткий URL. Плохо, если кандидат сильно перезакладывается или берет слишком маленькое количество символов, что может привести к тому, что допустимые комбинации в обозримом будущем закончатся;
- дополнительно можно углубиться в смежные темы: деплой/мониторинг сервиса в том или ином виде в зависимости от выбора в предыдущих вопросах, приблизительная оценка ресурсов, минимально необходимых для эксплуатации, отказоустойчивость.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25🔥5❤2
Загрузка из «плохого» 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
👍18❤4🔥1
***
Что такое транзакция? Приведите пример, где это может пригодиться. Расскажите про свойства транзакций и уровень изолированности.
Ответ
Транзакция объединяет последовательность действий в одну операцию и обеспечивает выполнение либо всех действий из последовательности, либо ни одного. Канонический пример — списывание денег с одного счета и зачисление на другой, что требует два 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
👍30❤8🔥1
Ответ
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
👍33🥰2❤1