ch
Feedback
Библиотека Go для собеса | вопросы с собеседований

Библиотека Go для собеса | вопросы с собеседований

前往频道在 Telegram

Вопросы с собеседований по Go и ответы на них. Учиться у нас: https://proglib.io/w/0b524a15 По рекламе: @proglib_adv Для обратной связи: @proglibrary_feeedback_bot Наши каналы: https://t.me/proglibrary/9197

显示更多
7 425
订阅者
-524 小时
-77
+630
帖子存档
💬 Назовите основные способы создания среза в Go. Предположим, что тип нового создаваемого среза — это S, а s0 — это нулевое значение литерала типа S. 1. Использование составных литералов:
// или 
var aSlice = S{Len - 1: s0} // длина и емкость равны Len (константа) 
  
Емкость результирующего среза не всегда выравнивается по размеру класса памяти. 2. Использование встроенной функции make:

// или 
var aSlice = make(S, initialLength) // емкость == initialLength 
  
Емкость результирующего среза не всегда выравнивается по размеру класса памяти. 3. Использование встроенных функций append + make):

// или 
var aSlice = append(S(nil), make(S, initialLength)...) 
// или 
var aSlice = append(S{}, make(S, initialLength, capacity)...) 
// или 
var aSlice = append(S(nil), make(S, initialLength, capacity)...) 
  
С официальным Go-инструментарием емкость результирующего среза выравнивается по размеру класса памяти.

🧑‍💻 Статьи для IT: как объяснять и распространять значимые идеи Напоминаем, что у нас есть бесплатный курс для всех, кто хо
🧑‍💻 Статьи для IT: как объяснять и распространять значимые идеи Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом. Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций. Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах. 👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.

💬 Перечислите все способы клонирования срезов на Go? 1️⃣ Использование make и copy

cloned := make(SliceType, len(aSlice))
copy(cloned, aSlice)
2️⃣ Более развернутая форма 1 способа

var cloned SliceType
if aSlice != nil {
    cloned = make(SliceType, len(aSlice))
    copy(cloned, aSlice)
}
3️⃣ Использование make и append

append(make(SliceType, 0, len(aSlice)), aSlice...)
4️⃣ Использование append

append(SliceType(nil), aSlice...) // Вариант 1
// или
append(SliceType{}, aSlice...) // Вариант 2
5️⃣ Другой способ использования append

append(aSlice[:0:0], aSlice...)
6️⃣ Использование slices.Clone (Go 1.21+)

import "slices"
slices.Clone(aSlice)

💬 Как получить адреса байтов строки в Go? 1. Использование unsafe до версии Go 1.22. До версии Go 1.22 получение адресов байтов строки было возможно только через пакет unsafe. Это небезопасный способ, но он работает:

package main

import (
    "unsafe"
)

func main() {
    str := "Hello, Go!"
    addr := unsafe.StringData(str)
    println(addr, string(*addr)) 
}
2. Использование reflect с версии Go 1.23 Начиная с версии Go 1.23, метод reflect.Value.UnsafePointer позволяет получить адреса байтов строки:

package main

import (
    "reflect"
)

func main() {
    str := "Hello, Go!"
    addr := (*byte)(reflect.ValueOf(str).UnsafePointer())
    println(addr, string(*addr)) 
}
3. Конвертация строки в срез байтов. С версии Go 1.22 была добавлена оптимизация, которая позволяет конвертировать строки в срезы байтов без копирования памяти, если байты не будут изменяться. Это позволяет безопасно получать адреса байтов строки:

package main

func main() {
    str := "Hello, Go!"
    byteSlice := []byte(str)
    addr := &byteSlice[0]
    println(addr, string(*addr)) 
}

✍️ «Библиотека программиста» находится в поиске автора на написание книжных рецензий Кто нужен? ● Энтузиасты (джуны и выше), которые которые разбираются в IT ● Любители книг, которые хотели бы получать деньги за чтение и написание рецензий ● Работаем с самозанятыми (компенсируем налог), ИП Мы предлагаем частичную занятость и полностью удаленный формат работы — можно совмещать с основной и находиться в любом месте🌴 ✉️ Станьте частью нашей команды — присылайте резюме и примеры работ hello@proglib.io

💵⚡️ДАРИМ 40 000₽ ЗА ВИДЕО Конкурс года в «Библиотеке программиста»: смонтируйте короткий вертикальный ролик формата Shorts/R
💵⚡️ДАРИМ 40 000₽ ЗА ВИДЕО Конкурс года в «Библиотеке программиста»: смонтируйте короткий вертикальный ролик формата Shorts/Reels* на тему программирования и разработки — лучший автор получит 40 тысяч рублей 🤑 Подробные условия: ➡️смонтируйте короткий смешной вертикальный ролик (можно и нужно использовать мемы) ➡️отправьте нам в бота @ProglibContest_bot ➡️лучшие ролики (по мнению редакции) мы будем выкладывать в канал и в наш инстаграм* ➡️тот, чей ролик соберет больше всего просмотров в инстаграм*, получит приз — 40 тысяч рублей Какие ролики мы не принимаем: 😟не вашего авторства (проверим!) 😟длинные, невертикальные, несмешные Таймлайн: 2 августа — заканчиваем принимать видео ⬇️ 3 августа — начинаем загружать лучшие видео в инстаграм ⬇️ 9 августа — подводим итоги *Организация Meta признана экстремистской в РФ

💬 Как итерироваться по рунам в строке Go? Для получения рун в строке достаточно использовать конструкцию for-range.
for i, rune := range aString {
    ... // используем руну
}
Руна может состоять из 1-4 байтов в UTF-8. Здесь i является начальным индексом байтов руны. Если нам нужно не только получить сами руны, но и их длину, удобным способом будет использование пакета unicode/utf8:
import "unicode/utf8"

var str = aString
for {
    rune, size := utf8.DecodeRuneInString(str)
    if size == 0 {
        break
    }
    str = str[size:]

    ... // используем руну
}

🔥Разработчики на Go! Вам нужны экстремальные результаты в разработке? Присоединяйтесь к нашему открытому онлайн вебинару «Как сделать быстрорастущий сервис с помощью трейсинга». Вы узнаете, как реализовать трейсинг для отслеживания выполнения запросов и выявления проблем. Мы покажем вам инструменты для анализа трейсов и наглядно рассмотрим работу сервиса под нагрузкой. Вы увидите, как с помощью трейсинга можно найти и устранить узкие места, даже если уже есть логирование. 🗣Спикер — DevOps-инженер в нескольких крупных проектах, опытный разработчик и преподаватель. ⏰ Встречаемся онлайн 25 июля в 20:00 мск. Регистрируйтесь прямо сейчас, чтобы не пропустить бесплатный урок: ➡️ РЕГИСТРАЦИЯ Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576 Erid 2VtzqvPUkNn

Открытое собеседование на Gо-разработчика в этот четверг 25 июля(уже в этот четверг!) в 19:00 по мск приходи онлайн на Открытое собеседование от Эйч Навыков. Как это будет: 1. Сергей Парамошкин, Deputy CTO в Yandex Cloud и ментор Эйч Навыков, позадает реальные вопросы и задачи разработчику-добровольцу 2. Потом Сережа даст подробную обратную связь — объяснит, зачем задавал тот или иной вопрос, как лучше на него ответить или решить задачу 3. В конце можно будет задать любой вопрос Сереже Что узнаешь на Открытом собеседовании: - Чего ждут от кандидатов на мидл-позиции в Gо-разработке - Какие вопросы задают на интервью и зачем - Как подготовиться к собесу, чтобы получить заветный оффер Это бесплатно? Бесплатно Просто зарегистрируйся на открытое собеседование в нашем боте @skills_mentee_bot Реклама: ООО “Эйч Карьера” erid: LjN8KRBeB

💬 Как использовать string canonicalization для экономии памяти? В Go, строки неизменяемы и часто одинаковые строки могут иметь разные блоки памяти. String canonicalization позволяет этим строкам делить один и тот же блок памяти, что может значительно сэкономить память. Рассмотрим два способа реализации на Go. 1️⃣ Первый способ предполагает, что когда две строки равны, одна строка может заменить другую, чтобы они делили одну и ту же память.

package main

import "fmt"

func CanonicalizeStrings(ss []string) {
 type S struct {
  str   string
  index int
 }
 var temp = make([]S, len(ss))
 for i := range temp {
  temp[i] = S{
   str:   ss[i],
   index: i,
  }
 }

 for i := 0; i < len(temp); {
  var k = i + 1
  for j := k; j < len(temp); j++ {
   if temp[j].str == temp[i].str {
    temp[j].str = temp[i].str
    temp[k], temp[j] = temp[j], temp[k]
    k++
   }
  }
  i = k
 }

 for i := range temp {
  ss[temp[i].index] = temp[i].str
 }
}

func main() {
 ss := []string{"hello", "world", "hello", "golang", "world"}
 CanonicalizeStrings(ss)
 fmt.Println(ss)
}
2️⃣ Использование unique.Handle, представленного в Go 1.23 Этот способ более удобен и гибок:.

package main

import (
 "fmt"
 "unique"
)

func CanonicalizeString(s string) string {
 return unique.Make(s).Value()
}

func CanonicalizeStrings(ss []string) {
 for i, s := range ss {
  ss[i] = CanonicalizeString(s)
 }
}

func main() {
 ss := []string{"hello", "world", "hello", "golang", "world"}
 CanonicalizeStrings(ss)
 fmt.Println(ss)
}

Ответьте на 3 вопроса, чтобы получить вводные занятия к курсу «Алгоритмы и структуры данных» 🔥Получите вводные занятия, отве
Ответьте на 3 вопроса, чтобы получить вводные занятия к курсу «Алгоритмы и структуры данных» 🔥Получите вводные занятия, ответив на 3 вопроса – https://proglib.io/w/e500f583 На вводной части вас ждут: 1. Лекция «Производительность алгоритмов» от руководителя разработки Яндекс.Самокатов; 2. Лекция «Итеративные сортировки и линейные сортировки» от аспирант департамента искусственного интеллекта ВШЭ; 3. Практические задания после лекций; 4. Ссылки на дополнительные материалы для самостоятельного изучения. ⚡️Переходите и начинайте учиться уже сегодня – https://proglib.io/w/e500f583

💬 Нужно ли лочить структуру мьютексом, если идет конкурентная запись в разные поля структуры? В Go структура данных не является автоматически потокобезопасной. Даже если мы записываем в разные поля структуры из разных горутин, могут возникнуть проблемы с синхронизацией, такие как race conditions. Основная причина использования мьютексов или других механизмов синхронизации заключается в том, чтобы обеспечить атомарность операций и предотвратить непредсказуемое поведение, которое может возникнуть из-за конкурентного доступа к данным. Рассмотрим пример структуры с двумя полями, которые обновляются конкурентно:

package main

import (
    "fmt"
    "sync"
)

type Data struct {
    Field1 int
    Field2 int
    mu     sync.Mutex
}

func main() {
    d := &Data{}

    var wg sync.WaitGroup

    // Запись в Field1
    wg.Add(1)
    go func() {
        defer wg.Done()
        for i := 0; i < 1000; i++ {
            d.mu.Lock()
            d.Field1 = i
            d.mu.Unlock()
 }
    }()

    // Запись в Field2
    wg.Add(1)
    go func() {
        defer wg.Done()
        for i := 0; i < 1000; i++ {
            d.mu.Lock()
            d.Field2 = i
            d.mu.Unlock()
        }
    }()

    wg.Wait()
    fmt.Println("Field1:", d.Field1)
    fmt.Println("Field2:", d.Field2)
}
1. Мы используем мьютекс (d.mu.Lock() и d.mu.Unlock()) для защиты записи в структуру Data. Даже если запись происходит в разные поля структуры, мьютекс гарантирует, что только одна горутина имеет доступ к структуре в любой момент времени. 2. Использование мьютекса предотвращает гонки данных и гарантирует корректное обновление полей структуры. Если известно, что запись в разные поля не приведет к гонкам данных (например, поля абсолютно независимы и нет побочных эффектов), можно обойтись без мьютекса. Однако это решение требует глубокого понимания контекста и потенциальных рисков.

💬 Назовите основные юзкейсы для контекста WithoutCancel. Основные кейсы для использования context.WithoutCancel (Go 1.21+) включают ситуации, когда необходимо гарантировать завершение определенных операций независимо от отмены родительского контекста. В таких случаях WithoutCancel помогает изолировать часть логики, которая не должна прерываться. Вот несколько конкретных примеров: 1. Фоновые задачи: когда необходимо выполнять фоновую операцию, такую как обновление кеша или периодическая синхронизация данных, важно, чтобы эти процессы не прерывались отменой основного контекста. Использование WithoutCancel гарантирует, что такие фоновые задачи продолжат выполнение до завершения. 2. Логирование и мониторинг: в системах, где логирование критически важно, необходимо гарантировать, что операции записи логов завершатся, даже если родительский контекст был отменен. Это помогает сохранить целостность логов и иметь полную информацию о произошедших событиях. 3. Rollback: в случае возникновения ошибки в транзакции или критической операции необходимо гарантировать, что операции отката будут выполнены полностью, даже если основной контекст был отменен. Это важно для поддержания согласованности данных. 4. Задачи с высоким приоритетом завершения: некоторые задачи должны быть завершены независимо от внешних факторов. Это могут быть операции, связанные с безопасностью, или критически важные операции системы.

💬 Как горутина, выполняющая блокирующий системный вызов, перемещается в глобальную очередь готовых к выполнению горутин в рантайме Go. Какие этапы проходят при этом? Когда горутина выполняет блокирующий системный вызов, она блокируется и рантайм Go временно паркует её, освобождая поток (M) для выполнения других горутин. После завершения блокирующей операции горутина разблокируется и перемещается в глобальную очередь готовых к выполнению горутин. Планировщик Go затем выбирает горутину из глобальной очереди и назначает её на доступный поток (M) с логическим процессором (P) для продолжения выполнения. 📌 Пример:
package main

import (
    "fmt"
    "net/http"
    "time"
)

func main() {
    go fetch("http://example.com")
    fmt.Println("Fetching started")
    time.Sleep(5 * time.Second)
}

func fetch(url string) {
    resp, err := http.Get(url)
    if err != nil {
        fmt.Println("Error fetching URL:", err)
        return
    }
    defer resp.Body.Close()
    fmt.Println("Fetched", url, "with status:", resp.Status)
}
Он демонстрирует, как горутина fetch блокируется на HTTP-запросе, освобождает поток, и после завершения системного вызова возвращается в глобальную очередь для продолжения выполнения.

🏃 Самоучитель по Go для начинающих. Часть 14. Интерфейсы ввода-вывода. Буферизация. Работа с файлами. Пакеты io, bufio, os В
🏃 Самоучитель по Go для начинающих. Часть 14. Интерфейсы ввода-вывода. Буферизация. Работа с файлами. Пакеты io, bufio, os В этой статье рассмотрим основные методы ввода-вывода из пакета io, изучим механизм буферизации и его применение в Go, а также разберем, как работать с файлами с помощью пакета os. 👉 Читать гайд 📌 Остальные части в серии: 1. Особенности и сфера применения Go, установка, настройка 2. Ресурсы для изучения Go с нуля 3. Организация кода. Пакеты, импорты, модули. Ввод-вывод текста. 4. Переменные. Типы данных и их преобразования. Основные операторы 5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы 6. Функции и аргументы. Области видимости. Рекурсия. Defer 7. Массивы и слайсы. Append и сopy. Пакет slices 8. Строки, руны, байты. Пакет strings. Хеш-таблица (map) 9. Структуры и методы. Интерфейсы. Указатели. Основы ООП 10. Введение в ООП. Наследование, абстракция, полиморфизм, инкапсуляция 11. Обработка ошибок. Паника. Восстановление. Логирование 12. Обобщенное программирование. Дженерики 13. Работа с датой и временем. Пакет time

💬 Есть четыре микросервиса: A → B → C → D. Как обеспечить согласованность данных? Чтобы обеспечить согласованность данных в такой цепочке микросервисов, мы можем использовать несколько подходов: 1. Распределенный мьютекс для синхронизации доступа к общим ресурсам и предотвращения гонок данных. 2. Распределенные транзакции для обеспечения атомарности операций между микросервисами можно использовать протокол двухфазного коммита (2PC). Это гарантирует, что все изменения будут применены одновременно или откатятся в случае ошибки. 3. Паттерн Saga, который представляет собой набор локальных транзакций. Каждая локальная транзакция обновляет базу данных и публикует сообщение или событие, инициируя следующую локальную транзакцию в саге. Если транзакция завершилась неудачей, например, из-за нарушения бизнес правил, тогда сага запускает компенсирующие транзакции, которые откатывают изменения, сделанные предшествующими локальными транзакциями.

Ищем Middle и Senior Гоферов, чтобы проводить тестовые собесы и менторить Привет! Это Эйч Навыки — команда разработчиков из б
Ищем Middle и Senior Гоферов, чтобы проводить тестовые собесы и менторить Привет! Это Эйч Навыки — команда разработчиков из бигтеха и менторская платформа. Мы давно помогаем найти крутую работу, апнуть грейд или свичнуть стек. Мы решили прийти сюда, чтобы найти новых классных коллег-менторов, которые хотят внести вклад в комьюнити и вырасти, обучая других. И готовы на доп.занятость — это пару часов в день. Надо будет проводить тестовые интервью с другими разработчиками → оценивать уровень этих ребят → помогать им расти дальше с помощью менторства. Если ты до этого никого не менторил, вообще не переживай — всему научим. Что взамен: 🔵 От 40К за 5-7 часов работы в неделю 🔵 Доступ к обучению и комьюнити других сильных менторов из Яндекса, Авито, Uber, Tinkoff и других 🔵 Возможность выступать на нашем YouTube-канале (там в среднем 5000 просмотров на видео) — так станешь заметнее на рынке 🔵 Жёсткая прокачка софтов + классная строчка в резюме. «Провел(а) 100+ собеседований» — звучит круто, работодатели точно оценят. Если хочешь попробовать себя в роли ментора, переходи в бота — мы свяжемся с тобой и расскажем подробности ➡️ @skills_mentee_bot Реклама: ООО “Эйч Карьера” erid: LjN8KXuGo

💬 Как можно проверить тип переменной во время выполнения в Go? В Go мы можем использовать switch для проверки типа переменной во время выполнения. Он называется type switch. Рассмотрим пример, где мы проверяем тип переменной v и выполняем определенный набор операций.
switch v := param.(type) {
default:
    fmt.Printf("Unexpected type %T", v)
case uint64:
    fmt.Println("Integer type")
case string:
    fmt.Println("String type")
}

💬 Что из себя представляют методы в Go? Методы в Go — это функции, прикрепленные к типам, включая структуры. Синтаксис объявления метода похож на синтаксис объявления функции, за исключением дополнительного аргумента ресивера перед именем функции, указывающего на тип, к которому прикрепляется метод. В вызове метода экземпляр типа будет доступен по имени аргумента ресивера. Возьмем для примера тип Vertex и добавим к нему метод Square, указав ресивер с именем v и типом *Vertex:

package main

import "fmt"

type Vertex struct {
    X, Y int
}

func (v *Vertex) Square() { метод к типу *Vertex
    v.X *= v.X
    v.Y *= v.Y
}

func main() {
    vert := &Vertex{3, 4}
    fmt.Println(vert) // &{3 4}
    vert.Square()
    fmt.Println(vert) // &{9 16}
}
Метод Square изменяет значения полей X и Y структуры Vertex на их квадраты. Вызов vert.Square() изменяет vert на &{9 16}. Помимо структур можно также создавать свои версии стандартных составных типов — структур, срезов или ассоциативных массивов — и присоединять к ним свои методы. Например, объявим новый тип MyMap, версию стандартного ассоциативного массива map[string]int, и присоединим к нему метод Length:

package main

import "fmt"

type MyMap map[string]int

func (m MyMap) Length() int {
    return len(m)
}

func main() {
    mm := MyMap{"A": 1, "B": 2}
    fmt.Println(mm)          // map[A:1 B:2]
    fmt.Println(mm["A"])     // 1
    fmt.Println(mm.Length()) // 2
}
Результатом является новый тип MyMap, отображающий строки в целые числа подобно map[string]int, но имеющий дополнительный метод Length, который возвращает количество элементов в массиве.

💬 Что из себя представляет netpoller в контексте Go? Netpoller — это механизм, встроенный в рантайм Go, который занимается мониторингом сетевых сокетов для I/O операций, используя модели мультиплексирования событий, такие как epoll на Linux, kqueue на BSD системах и macOS, и IOCP на Windows. Основная задача netpoller заключается в отслеживании событий ввода-вывода на сетевых сокетах (готовность чтения или записи данных). Это позволяет рантайму Go эффективно обрабатывать множество сетевых соединений одновременно, используя минимальное количество потоков. Когда Go-программа выполняет сетевую операцию, она регистрирует соответствующий сокет в netpoller. 🔸 Netpoller отслеживает эти сокеты и уведомляет Go рантайм, когда один из них готов для выполнения I/O операции. 🔸 Это уведомление передается планировщику Go, который назначает выполнение соответствующей горутины, связанной с этим сокетом.