Синглтон в ходу - PullRequest
       25

Синглтон в ходу

30 голосов
/ 01 декабря 2009

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

Ответы [ 8 ]

37 голосов
/ 03 декабря 2009

Если оставить в стороне аргумент того, является ли реализация шаблона синглтона хорошей идеей, вот возможная реализация:

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(), и он отслеживает количество экземпляров с помощью частного логического значения 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
}

См. Также, предложение Хасана j просто думать о пакете как как о синглтоне. И, наконец, подумайте над тем, что предлагают другие: синглтоны часто являются индикатором проблемной реализации.

11 голосов
/ 01 декабря 2009

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

Таким образом, с течением времени люди находят, что число синглетов меньше оптимального, и imho особенно , если вы пытаетесь сделать какую-либо разработку, основанную на тестировании: на многих уровнях они в значительной степени такие же плохие, как и глобальные переменные.

[Отказ от ответственности: я знаю, что это не строгий ответ на ваш вопрос, но это действительно актуально]

9 голосов
/ 01 декабря 2009

Просто поместите ваши переменные и функции на уровне пакета.

Также смотрите аналогичный вопрос: Как сделать синглтон в Python

8 голосов
/ 19 ноября 2012

Я думаю, что в параллельном мире нам нужно немного больше осознавать, что эти строки не выполняются атомарно:

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 голосов
/ 29 октября 2015

Лучший подход будет:

 package singleton

 import "sync"

 type singleton struct {
 }

 var instance *singleton
 var once sync.Once

 func GetInstance() *singleton {
     once.Do(func() {
         instance = &singleton{}
     })
     return instance
 }

Вы должны прочитать это Ссылка

3 голосов
/ 01 декабря 2009

Вы можете выполнить инициализацию, используя пакет Once :

Это гарантирует, что ваши методы init будут вызываться только один раз.

1 голос
/ 07 января 2016

Вы должны знать, что Once.Do серьезно относится к выполнению кода только один раз. Это означает, что код всегда выполняется только один раз, даже если он запаниковал:

от https://golang.org/pkg/sync/#Once.Do

Если f (примечание: однажды логика) паникует, Do считает, что он вернулся; будущие вызовы Do возвращаются без вызова f.

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

1 голос
/ 01 декабря 2009

Просто имейте один статический, конечный, постоянный, глобальный экземпляр объекта, который вы хотите.

Это, однако, противоречит парадигме ОО. Его использование должно быть ограничено примитивами и неизменяемыми объектами, а не изменяемыми объектами.

...