Как реализовать шаблон проектирования Singleton на языке программирования go?
Синглтон в движении
Ответ 1
Отключение аргумента о том, является ли реализация одноэлементного шаблона отличной идеей, может быть реализована:
package singleton
type single struct {
O interface{};
}
var instantiated *single = nil
func New() *single {
if instantiated == nil {
instantiated = new(single);
}
return instantiated;
}
single
и instantiated
являются закрытыми, но New()
является общедоступным. Таким образом, вы не можете напрямую создавать single
без прохождения New()
и отслеживать количество экземпляров с помощью private boolean instantiated
. Отрегулируйте определение single
по вкусу.
Однако, поскольку некоторые другие отмечены, это не является потокобезопасным, если только вы не инициализируете свой синглтон в init()
. Лучшим подходом было бы использовать sync.Once
для тяжелой работы для вас:
package singleton
import "sync"
type single struct {
O interface{};
}
var instantiated *single
var once sync.Once
func New() *single {
once.Do(func() {
instantiated = &single{}
})
return instantiated
}
См. также, hasan j предложение просто думать о пакете как singleton. И, наконец, подумайте о том, что предлагают другие: синглтоны часто являются индикатором проблематичной реализации.
Ответ 2
Прежде чем пытаться найти способ сгибания, перейдите к своей воле, вы можете взглянуть на некоторые статьи:
В итоге, со временем люди обнаружили, что синглтоны являются менее оптимальными, и imho особенно, если вы пытаетесь выполнить любую тестовую разработку: на многих уровнях они в значительной степени хуже глобальных переменных.
[отказ от ответственности: я знаю, что это не строгий ответ на ваш вопрос, но это действительно актуально]
Ответ 3
Просто поставьте свои переменные и функции на уровне пакета.
Также см. аналогичный вопрос: Как сделать singleton в Python
Ответ 4
Я думаю, что в параллельном мире нам нужно быть немного более осведомленным о том, что эти строки не выполняются атомарно:
if instantiated == nil {
instantiated = new(single);
}
Я буду следовать предложению @marketer и использовать пакет "sync"
import "sync"
type MySingleton struct {
}
var _init_ctx sync.Once
var _instance *MySingleton
func New() * MySingleton {
_init_ctx.Do( func () { _instance = new(MySingleton) } )
return _instance
}
Ответ 5
Лучшим подходом будет:
package singleton
import "sync"
type singleton struct {
}
var instance *singleton
var once sync.Once
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
Вы должны прочитать это Ссылка
Ответ 6
Вы можете выполнить инициализацию, используя один раз пакет:
Это обеспечит, чтобы ваши методы init вызывались только один раз.
Ответ 7
Просто у вас есть один статический, окончательный, постоянный, глобальный экземпляр объекта Object, который вы хотите.
Это, однако, противоречит парадигме ОО. Его использование должно быть ограничено примитивами и неизменяемыми объектами, а не изменчивыми объектами.
Ответ 8
Вы должны знать, что Once.Do
серьезно относится к выполнению кода только один раз. Это означает, что код всегда выполняется только один раз, даже если он мог бы запаниковать:
из https://golang.org/pkg/sync/#Once.Do
Если f (обратите внимание: когда-то логическая) паника, Do считает, что она вернулась; будущие вызовы Do возвращаются без вызова f.
Вместо этого я использовал мьютексы, чтобы обеспечить уникальную инициализацию глобальной переменной конфигурации, чтобы преодолеть это ограничение: