← Назад к вопросам
Singleton паттерн в Go
1.0 Junior🔥 161 комментариев
#Основы Go
Условие
Реализуйте потокобезопасный Singleton паттерн в Go.
Интерфейс
type Database struct {
connection string
}
func GetInstance() *Database
Требования
- Гарантировать создание только одного экземпляра
- Потокобезопасность при конкурентном доступе
- Ленивая инициализация (создание при первом вызове)
Вопросы
- Покажите решение с sync.Once
- Покажите решение с sync.Mutex
- В чем преимущества sync.Once?
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Singleton паттерн — создание только одного экземпляра объекта с потокобезопасным доступом.
Решение 1: sync.Once (РЕКОМЕНДУЕТСЯ)
var (
instance *Database
once sync.Once
)
func GetInstance() *Database {
once.Do(func() {
instance = &Database{
connection: "default-connection",
}
})
return instance
}
Преимущества sync.Once:
- Выполняет функцию ровно один раз при конкурентном доступе
- Минимальный overhead (проверка без lock после первого вызова)
- Стандартное решение в Go сообществе
- Самое простое и надёжное
Решение 2: sync.Mutex (явное управление)
type databaseHolder struct {
mu sync.Mutex
instance *Database
}
var holder = &databaseHolder{}
func GetInstance() *Database {
holder.mu.Lock()
defer holder.mu.Unlock()
if holder.instance == nil {
holder.instance = &Database{
connection: "default-connection",
}
}
return holder.instance
}
Минусы Mutex:
- Lock на каждый вызов (даже когда уже создан)
- Медленнее, чем sync.Once
- Может быть deadlock если не осторожны
Сравнение подходов
| Подход | Потокобезопасность | Ленивая инициализация | Производительность |
|---|---|---|---|
| sync.Once | Да | Да | Отличная |
| sync.Mutex | Да | Да | Хорошая |
| Double-checked | Ненадёжно | Да | Хорошая |
Тестирование
func TestSingletonConcurrency(t *testing.T) {
instances := make([]*Database, 100)
done := make(chan bool, 100)
for i := 0; i < 100; i++ {
go func(idx int) {
instances[idx] = GetInstance()
done <- true
}(i)
}
for i := 0; i < 100; i++ {
<-done
}
for i := 1; i < 100; i++ {
if instances[i] != instances[0] {
t.Error("Should be same instance")
}
}
}
Вывод
Используй sync.Once — это идеальное решение для Singleton в Go.