> Как контролировать уникальные указатели и умножать их ровно один раз в функции double в Go (Go)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: Т-Банк

Стек: Go

> Пример ответа

Короткий ответ

В Go нет умных указателей и оператора умножения для них - управление памятью осуществляется сборщиком мусора. Вопрос, вероятно, касается паттерна "double-checked locking" или идемпотентной инициализации через sync.Once. Для гарантии однократного выполнения используйте sync.Once или sync.Mutex с флагом. Умножение указателей в Go не имеет смысла - указатели можно только разыменовывать или сравнивать.

Подробное объяснение

В Go отсутствуют умные указатели вроде std::unique_ptr из C++. Управление памятью автоматическое, а указатели - это просто ссылки на объекты в куче или стеке. Операция "умножения" указателя не определена языком.

Если речь о паттерне "double-checked locking" для ленивой инициализации, то в Go его корректная реализация требует sync.Once или atomic + sync.Mutex. sync.Once гарантирует, что функция выполнится ровно один раз даже при конкурентном доступе.

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

На практике

Для однократной инициализации используйте sync.Once - это идиоматичный способ. Если нужен более тонкий контроль (например, сброс состояния), применяйте sync.Mutex с булевым флагом.

Для "умножения" значения по указателю - просто разыменуйте и умножьте: *ptr *= 2. Это безопасно, если указатель не nil и нет конкурентного доступа.

Пример кода

GO
package main
import (
"fmt"
"sync"
)
type Resource struct {
value int
}
var (
once sync.Once
resource *Resource
)
func getResource() *Resource {
once.Do(func() {
resource = &Resource{value: 42}
})
return resource
}
func double(ptr *int) {
if ptr == nil {
return
}
*ptr *= 2
}
func main() {
r := getResource()
double(&r.value)
fmt.Println(r.value) // 84
}

Как отвечать на собеседовании

Уточните, что именно имеется в виду: умные указатели из C++ или паттерн инициализации. Покажите понимание sync.Once и гонок данных. Объясните, почему в Go нет необходимости в умных указателях - GC решает проблему владения. Если спрашивают про double-checked locking, расскажите про sync.Once как более простую альтернативу.

Что проверяет интервьюер

  • Понимание модели памяти Go и отличий от C++.
  • Знание примитивов синхронизации (sync.Once, sync.Mutex, atomic).
  • Умение проектировать потокобезопасный код.
  • Внимание к деталям: nil-указатели, гонки данных.

Типичные ошибки

  • Попытка реализовать double-checked locking без atomic - это небезопасно.
  • Использование sync.Once для операций, которые могут завершиться ошибкой и требуют повторной попытки.
  • Забывание проверки на nil перед разыменованием.
  • Предположение, что в Go есть умные указатели - это сразу показывает непонимание языка.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью