Библиотека Go для собеса | вопросы с собеседований
6.87K subscribers
218 photos
6 videos
1 file
416 links
Вопросы с собеседований по Go и ответы на них.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/0b524a15

Для обратной связи: @proglibrary_feeedback_bot

Наши каналы: https://t.me/proglibrary/9197
Download Telegram
📖 ТОП-10 книг о том, как правильно построить карьеру в IT

Хотите преуспеть в IT? Ознакомьтесь с нашим списком лучших книг, которые помогут вам выстроить успешную карьеру в этой динамичной отрасли!

Читать статью, чтобы ознакомиться со всеми книгами 👉 https://proglib.io/sh/glq68BCSKj
👍1
💬 Что такое статическая компиляция/линковка и в чем ее особенности?

Линковка (или компоновка) — это последний этап сборки программы, когда все скомпилированные части кода и библиотеки объединяются в один исполняемый файл. Статически слинкованный исполняемый файл не зависит от наличия других библиотек в системе во время своей работы, так как все необходимые библиотеки встраиваются в итоговый бинарный файл.

Для включения статической компиляции/линковки в Go необходимо установить переменную окружения CGO_ENABLED=0 при сборке (т. е. `CGO_ENABLED=0 go build ...`). Это гарантирует, что все внешние библиотеки, от которых зависит выполнение кода, будут встроены в итоговый бинарный файл. Полученный бинарный файл можно использовать, например, в Docker-образе, основанном на scratch (т.е. не содержащем никаких файлов, чистая файловая система).

Однако, это накладывает некоторые ограничения и привносит особенности, которые необходимо помнить:

1. C-код будет недоступен. Некоторые модули из стандартной библиотеки Go зависят от C-кода, но они не являются критичными.
2. Не будет использоваться системный DNS-резольвер: Go будет использовать собственный DNS-резолвер.
3. Проблемы с проверкой x.509 сертификатов на MacOS: в некоторых случаях проверка x.509 сертификатов может не работать корректно.

Если итоговый бинарный файл планируется использовать в Docker-образе scratch, то также следует учитывать:

1. Корневые SSL/TLS сертификаты: для осуществления HTTP запросов по протоколу HTTPS нашему приложению, в образ нужно будет поместить корневые SSL/TLS сертификаты в /etc/ssl/certs.
2. Файл временной зоны: для корректной работы с датой и временем необходимо добавить файл временной зоны в /etc/timezone.
👍161
🖼️ Видеогайд про внутреннее устройство планировщика Go от Владимира Балуна

Таймкоды:

00:00 — Введение
03:00 — Потоки операционной системы
07:34 — Легковесные потоки
10:16 — Основные концепции рантайма Go
15:21 — Масштабирование рантайма Go
18:45 — Локальные очереди
21:45 — Work sharing и work stealing
26:08 — Syscalls в планировщике Go
27:41 — Handoff
34:50 — Netpoller
37:33 — Очереди в планировщике Go
42:28 — Примитивы синхронизации
48:57 — Циклы
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15
💬 Что значит work sharing и work stealing в контексте планировщика в Go?

Задача планировщика в Go — распределять запущенные горутины между потоками ОС, которые могут исполняться одним или большим количеством процессоров. В многопоточных вычислениях возникли две парадигмы в планировании: делиться задачами (work sharing) и красть задачи (work stealing).

🔹 Work-sharing: когда процессор генерирует новые потоки, он пытается мигрировать их на другие процессоры, в надежде, что они попадут к простаивающему или недостаточно нагруженному процессору.
🔹 Work-stealing: недостаточно нагруженный процессор активно ищет потоки других процессоров и «крадет» некоторые из них.

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

В Go начиная с версии 1.1 планировщик реализован по схеме work stealing.
👍8
🧑‍💻 Статьи для IT: как объяснять и распространять значимые идеи

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

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

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

👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
💬 Каковы основные отличия HTTP/3 от предыдущих версий HTTP (HTTP/1.1 и HTTP/2)?

HTTP/3 отличается от HTTP/1.1 и HTTP/2 несколькими ключевыми аспектами:

1. Транспортный протокол:

🔸 HTTP/1.1 и HTTP/2: оба используют TCP для передачи данных. TCP обеспечивает надежную доставку, но может страдать от задержек при потере пакетов из-за необходимости восстановления всего потока данных.
🔸 HTTP/3: использует протокол QUIC (Quick UDP Internet Connections), который построен поверх UDP. QUIC обеспечивает быструю и надежную доставку данных с меньшими задержками, т. к. каждый пакет обрабатывается независимо.

2. Установка соединения:
🔸 HTTP/1.1 и HTTP/2: для установки соединения требуется несколько этапов, включая установку TCP соединения и выполнение TLS рукопожатия.
🔸 HTTP/3: снижает задержки при установке соединения за счет одновременного выполнения рукопожатия QUIC и TLS, что позволяет начать передачу данных быстрее.

3. Управление задержками и потерями пакетов:
🔸 HTTP/1.1 и HTTP/2: при потере пакета в TCP соединении, весь поток данных останавливается до тех пор, пока потерянный пакет не будет восстановлен, что увеличивает задержки.
🔸 HTTP/3: QUIC минимизирует влияние потери пакетов, т. к. каждый поток данных внутри соединения обрабатывается независимо. Это означает, что потеря одного пакета не блокирует другие потоки данных.

4. Мультиплексирование:
🔸 HTTP/1.1: не поддерживает мультиплексирование, каждый запрос требует отдельного соединения.
🔸 HTTP/2: поддерживает мультиплексирование, позволяя отправлять несколько запросов и ответов через одно соединение.
🔸 HTTP/3: также поддерживает мультиплексирование, но делает это более эффективно благодаря особенностям QUIC.

📌 Подробнее:

🔗 Cloudflare: What is HTTP/3?
🔗 Google: HTTP/3 Explained
11👍1
💬 Как развернуть односвязный список в Go? Приведите пример кода, который создает три элемента односвязного списка, связывает их последовательно и разворачивает этот список в обратную сторону.

Для разворота односвязного списка в Go нужно создать структуру для представления узлов списка, инициализировать элементы списка, связать их, а затем развернуть их порядок

package main

import (
"fmt"
)

// Определение структуры узла односвязного списка
type LinkNode struct {
next *LinkNode
value int
}

// Метод для печати элементов списка
func (l *LinkNode) Print() {
for current := l; current != nil; current = current.next {
fmt.Print(current.value)
if current.next != nil {
fmt.Print(" -> ")
}
}
fmt.Println()
}

func main() {
// Инициализация элементов списка
var n1, n2, n3 = LinkNode{value: 1}, LinkNode{value: 2}, LinkNode{value: 3}
// Связывание элементов
n1.next, n2.next = &n2, &n3

// Вывод исходного списка
fmt.Println("Исходный список:")
n1.Print() // 1 -> 2 -> 3

// Разворот списка
var prev, next *LinkNode
for current := &n1; current != nil; {
next, current.next = current.next, prev
prev, current = current, next
}

// Вывод развернутого списка
fmt.Println("Развернутый список:")
prev.Print() // 3 -> 2 -> 1
}
👍6
💬 Какие типы баз данных существуют?

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

📌 Вот основные типы баз данных:

1. Реляционные:
🔸 Описание: хранение данных в виде таблиц, связанных между собой ключами. Основой являются строки и столбцы.
🔸 Примеры: MySQL, PostgreSQL, Oracle Database, Microsoft SQL Server.
🔸 Использование: применяются для большинства бизнес-приложений, где важны транзакционная целостность и согласованность данных.

2. Документные:
🔸 Описание: хранение данных в виде документов (обычно JSON или BSON). Документы могут содержать сложные, вложенные структуры.
🔸 Примеры: MongoDB, CouchDB.
🔸 Использование: идеальны для приложений с динамическими схемами, таких как веб-приложения и контент-менеджмент системы.

3. Ключ-значение:
🔸 Описание: хранение данных в виде пар ключ-значение. Простой и быстрый доступ к данным по ключу.
🔸 Примеры: Redis, DynamoDB, Riak.
🔸 Использование: часто используются для кэширования, сессий пользователя и других задач, требующих высокой производительности.

4. Графовые:
🔸 Описание: хранение данных в виде графов с узлами и рёбрами. Идеальны для представления связей и взаимосвязей между данными.
🔸 Примеры: Neo4j, JanusGraph.
🔸 Использование: социальные сети, системы управления рекомендациями, аналитика сетей.

5. Столбцовые:
🔸 Описание: хранение данных по столбцам, а не по строкам. Позволяют эффективно выполнять аналитические запросы.
🔸 Примеры: Apache Cassandra, HBase, Google Bigtable.
🔸 Использование: большие аналитические системы, хранилища данных.

6. Расширяемые хранилища записей:
🔸 Описание: гибрид ключ-значение и столбцовых баз данных, где данные хранятся в виде больших, широко распределённых таблиц.
🔸 Примеры: Google Bigtable, Apache Cassandra.
🔸 Использование: приложения, требующие горизонтальной масштабируемости и быстрой обработки больших объёмов данных.

7. Многомерные:
🔸 Описание: специализированные базы данных для обработки и анализа многомерных данных, часто используются в OLAP.
🔸 Примеры: IBM Cognos TM1, Microsoft Analysis Services.
🔸 Использование: бизнес-аналитика, финансовое планирование.

8. Встраиваемые:
🔸 Описание: встраиваются в приложения и работают автономно без необходимости установки и обслуживания сервера баз данных.
🔸 Примеры: SQLite, Berkeley DB.
🔸 Использование: мобильные приложения, десктопные приложения, устройства IoT.

9. NoSQL:
🔸 Описание: объединяют различные типы баз данных, которые не используют реляционную модель. Подразделяются на документные, графовые, ключ-значение и столбцовые базы данных.
🔸 Примеры: MongoDB, Neo4j, Cassandra, Redis.
🔸 Использование: гибкость схемы, горизонтальная масштабируемость, обработка больших данных.

10. In-Memory:
🔸 Описание: хранят данные в оперативной памяти для обеспечения высокой скорости доступа.
🔸 Примеры: Redis, Memcached, SAP HANA.
🔸 Использование: реализация кэша, временных хранилищ, аналитика в реальном времени.

11. NewSQL:
🔸 Описание: сочетают преимущества реляционных баз данных и NoSQL, обеспечивая высокую производительность и масштабируемость.
🔸 Примеры: Google Spanner, CockroachDB, VoltDB.
🔸 Использование: приложения, требующие высокой согласованности и масштабируемости.
5👍2😁1
🖼️ А как бы вы её решили?👇
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯 Как простая задачка поставила в тупик программистов (и как они из него выбрались)

В 2010 году пользователь Stack Overflow не справился с задачей на собеседовании. Обсуждение способов решения этого задания стало одной из самых популярных тем на платформе.

Об этой истории, а также о способах решения задачи, читайте в нашей статье
👉 Ссылка
👉 Зеркало
🥱4
💬 Что означает понятие false sharing?

False sharing — это ситуация, когда ядра начинают мешать друг другу. У каждого из ядер есть свой L1 Cache, который поделён на линии (cache Line) по 64 байта. Когда мы получаем какие-то данные из памяти, мы всегда получаем не меньше, чем 64 байта. Изменяя эти данные, мы инвалидируем кэши всех ядер.

Получается, что если два ядра меняют очень близкие друг к другу данные (на расстоянии меньше 64-х байт), они начинают друг другу мешать, инвалидируя кэши. В этом случае, если бы программа была написана последовательно, она работала бы быстрее, чем при использовании нескольких ядер, которые друг другу мешают. Чем больше ядер, тем меньшая производительность получится.
🤔11👍3🥱2
💬 Что из себя представляет CAP-теорема (теорема Брюера)?

CAP-теорема утверждает, что в любой реализации распределённых вычислений можно обеспечить не более двух из трёх следующих свойств:

1. Согласованность данных (Consistency): как только мы успешно записали данные в наше распределенное хранилище, любой клиент при запросе получит актуальные данные.
2. Доступность (Availability): в любой момент клиент может получить данные из нашего хранилища или получить ответ об их отсутствии, если их никто еще не сохранял.
3. Устойчивость к разделению (Partition Tolerance): потеря сообщений между компонентами системы (возможно даже потеря всех сообщений) не влияет на работоспособность системы.

📌 Распределенные системы и CAP-теорема

Распределённые системы, в зависимости от поддерживаемых двух из трёх свойств CAP-теоремы, делятся на три категории:

1. CA (Consistency + Availability):
🔸 Во всех узлах данные согласованы и обеспечена доступность. При этом система жертвует устойчивостью к разделению.
🔸 Пример: системы, использующие репликацию данных и требуют синхронного подтверждения от всех узлов (в условиях отсутствия разделений).

2. CP (Consistency + Partition Tolerance):
🔸 В каждый момент система обеспечивает целостный результат и способна функционировать в условиях разделения, но достигает этого в ущерб доступности (может не выдавать отклик на запрос).
🔸 Пример: системы баз данных, такие как HBase, где в условиях разделения данные остаются согласованными, но некоторые части системы могут быть недоступны.

3. AP (Availability + Partition Tolerance):
🔸 Не гарантируется целостность данных, но обеспечивается доступность и устойчивость к разделению.
🔸 Пример: системы, такие как Cassandra, которые обеспечивают доступность и устойчивость к разделению, но могут возвращать устаревшие данные.

Подробнее:
🔗 CAP-теорема простым, доступным языком
🔗 Недопонимание CAP-теоремы
7👍3
⚡️Proglib запускает канал про ИИ в сфере видео

Вот несколько топовых постов за последнее время:

⭐️Инструмент, который сам делает короткие вертикальные видео из ваших длинных роликов, например, на ютуб
⭐️Подборка нейро-генераторов видео с пробным периодом
⭐️Анонс ИИ-«нетфликса», который будет штамповать вам мультики по запросам

👉Подписывайтесь!
Please open Telegram to view this post
VIEW IN TELEGRAM
💬 Почему использование time.After для установки таймаутов может привести к утечке памяти в Go. Как можно предотвратить эту проблему?

Использование time.After для создания таймеров или установки таймаутов может привести к утечке памяти из-за особенностей работы сборщика мусора Go. Когда мы вызываем time.After(d), создается канал, который закроется после задержки d.

Однако таймер, созданный time.After, не будет собран сборщиком мусора до тех пор, пока не истечет задержка времени. Это означает, что даже если канал выходит из области видимости, он остается в памяти до тех пор, пока не истечет таймер.

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


func consumer(ch <-chan Event) {
for {
select {
case event := <-ch:
handle(event)
case <-time.After(time.Minute * 15) :
fmt.Println("warning: no messages received")
}
}
}


При высоком потоке событий это может привести к утечке памяти. Каждый раз, когда вызывается time.After, создается новый канал, который остается в памяти до истечения таймера.

📌 Как предотвратить проблему утечки памяти?

Для предотвращения этой проблемы можно использовать time.NewTimer и явным образом останавливать таймер, когда он больше не нужен:


func consumer(ch <-chan Event) {
for {
timer := time.NewTimer(time.Minute * 15)
select {
case event := <-ch:
handle(event)
if !timer.Stop() {
<-timer.C
}
case <-timer.C:
fmt.Println("warning: no messages received")
}
}
}


В примере таймер создается с использованием time.NewTimer, и мы явным образом останавливаем его с помощью timer.Stop() после обработки события. Это предотвращает создание множества неиспользуемых таймеров, которые могут привести к утечке памяти.

👉 Подробнее:
Go Documentation: time.After
Effective Go: Memory Management
Go Memory Management
👍211
💡 Если у вас запущено множество локальных серверов, и вам надоело обращаться к ним как localhost:8081, localhost:9000 и т. д., посмотрите в сторону Caddy. Он сделает настройку «доменов» для локальных серверов проще простого.

Предположим, у вас есть локальный сервер на порту 9000. После установки Caddy, выполните команду:


caddy reverse-proxy --from myserver.localhost --to :9000


и откройте https://myserver.localhost. Вы увидите, что сервер на localhost:9000 отвечает. Caddy даже предоставляет локальные TLS-сертификаты.

А если вы хотите проксировать больше серверов таким образом, создайте файл с именем Caddyfile и введите конфигурацию хоста следующим образом:


myapp.localhost {
reverse-proxy :9000
}

myhugoblog.localhost {
reverse-proxy :1313
}


#tip
🔥22👍2
✍️Библиотека программиста» находится в поиске автора оригинальных статей

Кто нужен?
● Энтузиасты (джуны и выше), которые держат руку на пульсе, читают помимо книг зарубежные техноблоги
● Энтузиасты, которым есть что сказать

Тематика
● DevOps
● В четырех случаях из пяти вы предлагаете тему статьи

Объем
● От 7 до 15 тыс. знаков без учета кода
● 2-3 статьи в месяц

Оплата
● 8к руб. за статью
● Работаем с самозанятыми (компенсируем налог), ИП

Я пишу «так себе», что делать?
Чтобы написать статью, которую не стыдно опубликовать, достаточно овладеть инфостилем. У нас есть бесплатный курс для начинающих копирайтеров «Статьи для IT: как объяснять и распространять значимые идеи». Время прохождения курса: 1-2 недели.

✉️Пишите на hello@proglib.io