Подтвердить что ты не робот

Синглтон в движении

Как реализовать шаблон проектирования Singleton на языке программирования go?

4b9b3361

Ответ 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.

Вместо этого я использовал мьютексы, чтобы обеспечить уникальную инициализацию глобальной переменной конфигурации, чтобы преодолеть это ограничение: