Есть ли особенности поведения при передаче map и slice в функцию?
Ответ
Передача slice и map может заставить усомниться в том, что они передаются в функцию по значению. Однако здесь так же происходит копирование. Структуры slice и map (уточнение: в случае map копируется не сама структура, а указатель структуру hmap, подробнее о том, что такое hmap можно прочитать в первой статье) копируются, однако в самих структурах содержатся ссылки на области памяти, благодаря которым создается эффект передачи по ссылке.
Вывод
Вывод
@golang_interview
Ответ
Передача slice и map может заставить усомниться в том, что они передаются в функцию по значению. Однако здесь так же происходит копирование. Структуры slice и map (уточнение: в случае map копируется не сама структура, а указатель структуру hmap, подробнее о том, что такое hmap можно прочитать в первой статье) копируются, однако в самих структурах содержатся ссылки на области памяти, благодаря которым создается эффект передачи по ссылке.
func main() {
slice := []int{1, 2, 3, 4, 5}
fmt.Println(slice)
fmt.Printf("%p\n", &slice)
changeZeroElem(slice)
fmt.Println(slice)
}
func changeZeroElem(slice []int) {
fmt.Printf("%p\n", &slice)
slice[0] = 99
}
Вывод
[1 2 3 4 5]
0xc0000ac018
0xc0000ac048
[99 2 3 4 5]
func main() {
store := map[string]int{"first": 1, "second": 2}
fmt.Println(store)
fmt.Printf("%p\n", &store)
changeMapElem(store)
fmt.Println(store)
}
func changeMapElem(store map[string]int) {
fmt.Printf("%p\n", &store)
store["first"] = 99
}
Вывод
map[first:1 second:2]
0xc0000b2018
0xc0000b2028
map[first:99 second:2]
@golang_interview
Каковы отличия context.WithCancel, context.WithDeadline, context.WithTimeout?
- context.WithCancel(parent Context) (ctx Context, cancel CancelFunc) создает контекст производный от родительского, также возвращает функцию отмены, с помощью которой этот контекст можно закрыть. Общепринятой практикой является работать с функцией отмены там, где она получена, не передавая ее глубже.
- context.WithDeadline(parent Context, d time.Time) (ctx Context, cancel CancelFunc) создает контекст производный от родительского, также возвращает функцию отмены, с помощью которой этот контекст можно закрыть. Контекст автоматически отменится в переданное, как входной параметр функции, время.
- context.WithTimeout(parent Context, timeout time.Duration) (ctx Context, cancel CancelFunc) создает контекст производный от родительского, также возвращает функцию отмены, с помощью которой этот контекст можно закрыть. Контекст автоматически отменится через интервал времени, переданный, как входной параметр функции.
@golang_interview
- context.WithCancel(parent Context) (ctx Context, cancel CancelFunc) создает контекст производный от родительского, также возвращает функцию отмены, с помощью которой этот контекст можно закрыть. Общепринятой практикой является работать с функцией отмены там, где она получена, не передавая ее глубже.
- context.WithDeadline(parent Context, d time.Time) (ctx Context, cancel CancelFunc) создает контекст производный от родительского, также возвращает функцию отмены, с помощью которой этот контекст можно закрыть. Контекст автоматически отменится в переданное, как входной параметр функции, время.
- context.WithTimeout(parent Context, timeout time.Duration) (ctx Context, cancel CancelFunc) создает контекст производный от родительского, также возвращает функцию отмены, с помощью которой этот контекст можно закрыть. Контекст автоматически отменится через интервал времени, переданный, как входной параметр функции.
@golang_interview
В равной ли степени горутины делят между собой процессорное время?
Ответ
Существует 2 типа многозадачности:
кооперативная - передачей управления процессы занимаются самостоятельно;
вытесняющая многозадачность - планировщик дает отработать процессам равное время, после чего перещелкивает контекст.
С версии Go 1.14 планировщик с кооперативного стал асинхронно вытесняющим. Сделано это было по причине долго отрабатывающих горутин, надолго занимающих процессорное время и не дающих доступа до него другим горутинам. Теперь когда горутина отрабатывает больше 10 м/с Go будет пытаться переключить контекст для выполнения следующей горутины. Казалось бы вот он ответ. Но не все так просто... Части кооперативного поведения до сих пор присутствуют, к примеру перед вытеснением горутины необходимо выполнить проверку куска кода на атомарность, с точки зрения garbage collector. Операция вытеснения может настичь горутину в любом месте, в зависимости от состояния данных, сборщик мусора может отработать совсем не так как ожидалось. Так как Go живой язык, в который постоянно вносятся изменения, реализация и тонкости в разных версиях могут отличаться. Настоятельно советую обновлять свои знания по этой теме по мере релизов Go.
@golang_interview
Ответ
Существует 2 типа многозадачности:
кооперативная - передачей управления процессы занимаются самостоятельно;
вытесняющая многозадачность - планировщик дает отработать процессам равное время, после чего перещелкивает контекст.
С версии Go 1.14 планировщик с кооперативного стал асинхронно вытесняющим. Сделано это было по причине долго отрабатывающих горутин, надолго занимающих процессорное время и не дающих доступа до него другим горутинам. Теперь когда горутина отрабатывает больше 10 м/с Go будет пытаться переключить контекст для выполнения следующей горутины. Казалось бы вот он ответ. Но не все так просто... Части кооперативного поведения до сих пор присутствуют, к примеру перед вытеснением горутины необходимо выполнить проверку куска кода на атомарность, с точки зрения garbage collector. Операция вытеснения может настичь горутину в любом месте, в зависимости от состояния данных, сборщик мусора может отработать совсем не так как ожидалось. Так как Go живой язык, в который постоянно вносятся изменения, реализация и тонкости в разных версиях могут отличаться. Настоятельно советую обновлять свои знания по этой теме по мере релизов Go.
@golang_interview
🔥 Полезнейшая Подборка каналов
👣 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
Что такое буферизированный и небуферизированный 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
Ответ
Если размышлять глобально, то таких способа 3:
- завершение main функции и main горутины;
- прослушивание всеми горутинами channel, при закрытии channel отправляется значение по умолчанию всем слушателям, при получении сигнала все горутины делают return;
- завязать все горутины на переданный в них context.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
На этот вопрос, ожидается ответ, не сколько весят все вместе взятые поля в структуре 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
Что такое 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
Для чего используется 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
Ответ
Это можно сделать через
runtime.GOMAXPROCS()
. Важно понимать, что при выставлении количества логических процессоров больше, чем есть у вас в системе, вы рискуете получить определенные проблемы с производительностью. Чтобы избежать этого можно задать runtime.GOMAXPROCS(runtime.NumCPU()), runtime.NumCPU() - количество логических процессоров.@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Как принудительно переключить контекст?
Ответ
Переключение контекста вручную осуществляется с помощью функции
@golang_interview
Ответ
Переключение контекста вручную осуществляется с помощью функции
runtime.Goshed()
.@golang_interview
Ответ
wait group;
mutex;
atomic;
sync map;
channel.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Для чего используется 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
Если размер стэка горутины превышен (к примеру запустили бесконечную рекурсию), то приложение упадет с 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
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
Golang online books, articles, tools, etc.
#практика
Необходимо реализовать сервис, позволяющий следить за изменением цены любого объявления на Авито (другой аналогичный сайт с объявлениями):
1. Сервис должен предоставить HTTP метод для подписки на изменение цены. На вход метод получает - ссылку на объявление, email на который присылать уведомления.
2.После успешной подписки, сервис должен следить за ценой объявления и присылать уведомления на указанный email.
3. Если несколько пользователей подписались на одно и тоже объявление, сервис не должен лишний раз проверять цену объявления.
Требования к решению
- Необходимо проработать архитектуру сервиса и описать принципиальную схему работы в виде текста и/или диаграмм.
- Приложить фрагменты кода, решающие конкретные задачи:
- Подписка на изменение цены
- Отслеживание изменений цены
- Отправка уведомления на почту
Работа с БД
- Язык программирования Golang.
Чтобы получить цену объявления, можно:
- парсить web-страницу объявления
- самостоятельно проанализировать трафик на мобильных приложениях или мобильном сайте и выяснить какой там API для получения информации об объявлении
Усложнения
- Реализовать полноценный сервис, который решает поставленную задачу (сервис должен запускаться в docker-контейнере).
- Написаны тесты (постарайтесь достичь покрытия в 70% и больше).
- Подтверждение email пользователя.
Ставьте ❤️, если вам интересно увидеть практические задания с реальных собеседований.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM
Нам нужно разбить процессы на несколько горутин — при этом не создавать новую горутину каждый раз, а просто переиспользовать уже имеющиеся. Для этого создадим канал с джобами и результирующий канал. Для каждого воркера создадим горутину, который будет ждать новую джобу, применять к ней заданную функцию и пулять ответ в результирующий канал.
Решение
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 разработчика.
Описание
Есть внешний сервис, который обрабатывает некие абстрактные объекты батчами. Данный сервис может обрабатывать только определенное количество элементов 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
Ваша компания отправляет СМС с трекинговой ссылкой, но ссылка достаточно длинная и из-за этого СМС выходит за 70 символов (длина 1 СМС). Необходимо спроектировать сервис-«укорачиватель ссылок» на языке GO, чтобы сэкономить деньги компании. Интервьюер при этом выступает заказчиком со стороны бизнеса и ему можно задавать вопросы по сути задачи.
Примечание
Задача хороша тем, что в нее можно углубляться по нескольким направлениям и оценить сразу несколько скиллов кандидата, а также глубину проработки (по сути его опыт), причём даже если он её уже решал (а многие действительно это делали). Основные направления обсуждения:
- как будем делать с точки зрения структуры приложения (в самом проекте/микросервисе и критерии, по которым мы делаем этот выбор). И тот, и другой варианты допустимы — все дело в аргументации. Если кандидат вообще не говорит про задачу с этой стороны, а, например, сразу переходит к структуре таблицы, то, скорее всего, кандидат никогда не задумывается над такими вопросами и/или не работал в более-менее крупных проектах;
- структура данных и выбор хранилища (СУБД, key-value типа Redis, еще какие-то варианты, плюсы и минусы тех или иных вариантов). Опять же, в зависимости от вопросов кандидата и желания интервьюера можно подвести к выбору какого-то варианта, но в целом есть множество вариантов реализации, которые будут оправданы — опять же, вопрос в аргументации выбора;
- хеши/коллизии, устойчивость к перебору ссылок (расчет количества необходимых вариантов). Важно, чтобы собеседуемый разработчик узнал про количество ссылок, оценил максимально возможную длину ссылки (и срок действия) и принял решение о том, какое количество символов стоит заложить в короткий URL. Плохо, если кандидат сильно перезакладывается или берет слишком маленькое количество символов, что может привести к тому, что допустимые комбинации в обозримом будущем закончатся;
- дополнительно можно углубиться в смежные темы: деплой/мониторинг сервиса в том или ином виде в зависимости от выбора в предыдущих вопросах, приблизительная оценка ресурсов, минимально необходимых для эксплуатации, отказоустойчивость.
@golang_interview
Please open Telegram to view this post
VIEW IN TELEGRAM