Вопрос

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

Это было полезно?

Решение

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

package singleton

type single struct {
        O interface{};
}

var instantiated *single = nil

func New() *single {
        if instantiated == nil {
                instantiated = new(single);
        }
        return instantiated;
}

single и экземпляр являются частными, но 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 просто думать о пакете как как об одиночке. И, наконец, подумайте над тем, что предлагают другие: синглтоны часто являются индикатором проблемной реализации.

Другие советы

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

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

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

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

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

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

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 
}

Наилучшим подходом будет:

 package singleton

 import "sync"

 type singleton struct {
 }

 var instance *singleton
 var once sync.Once

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

Вам следует прочитать эту ссылку

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top