Les subtilités de l'implémentation Singleton dans Golang

Salut les amis.





Je m'appelle Alex Versus et aujourd'hui nous allons jeter un œil au pattern Singleton , une implémentation dans le langage Golang .





À quoi ça sert?

Singleton - fait référence aux modèles génératifs. Garanti:





  • que la classe / le type n'a qu'une seule instance





  • lui fournit un point d'accès global.





Quel problème résout-il?

Parlons du problème que le modèle résout. Un solitaire résout deux problèmes à la fois, violant le principe de responsabilité unique (SRP) :





  1. Garantit qu'il existe une seule instance de l'objet. Ceci est utile pour accéder à une ressource partagée, telle qu'une base de données, ou lors de l'implémentation d'un mécanisme unique pour modifier une propriété, comme le niveau sonore dans un égaliseur.

    Imaginons que nous ayons une sorte d'objet et que vous en créez un autre après un certain temps, mais que vous aimeriez recevoir non pas un objet nouveau, mais déjà créé. Ce comportement ne peut pas être créé à l'aide d'outils standard tels que le constructeur dans les langages orientés objet.





  2. Fournissez un hotspot mondial. Veuillez noter qu'il ne s'agit pas simplement d'une variable globale à travers laquelle vous pouvez atteindre un objet spécifique. La variable globale ne vous protège pas contre l'écrasement de l'objet créé.





Les développeurs appellent souvent des objets Lonely qui n'effectuent qu'une seule tâche, comme indiqué ci-dessus. C'est un malentendu du modèle.





Quelle est la solution à Golang?

GOlang? , , , -. . . - . :





Diagramme de classe Singleton
Singleton

GOlang . . getInstance()



? singleton



:





// declaration defined type 
type singleton struct {
   
}
      
      



singleton



, nil:





// declare variable
var instance *singleton = nil
      
      



instance



sync.Once



. , . Sigleton



:





// defined type with interface
type Singleton interface {
// here will be methods
}
      
      



:





// Get only one object
func GetInstance() Singleton {
   once.Do(func() {
      instance = new(singleton)
   })
   return instance
}
      
      



singleton



, :





// declaration defined type
type singleton struct {
   title string
}
      
      



Singleton



, :





// defined type with interface
type Singleton interface {
   SetTitle(t string)
   GetTitle() string
}


// Setter for singleton variable
func (s *singleton) SetTitle(t string) {
   s.title = t
}

// Getter singleton variable
func (s *singleton) GetTitle() string {
   return s.title
}
      
      



.





, . , :





package Singleton

import "testing"

func TestGetInstance(t *testing.T) {
   var s Singleton
   s = GetInstance()
   if s == nil {
      t.Fatalf("First sigletone is nil")
   }

   s.SetTitle("First value")
   checkTitle := s.GetTitle()

   if checkTitle != "First value" {
      t.Errorf("First value is not setted")
   }

   var s2 Singleton
   s2 = GetInstance()
   if s2 != s {
      t.Error("New instance different")
   }

   s2.SetTitle("New title")
   newTitle := s.GetTitle()
   if newTitle != "New title" {
      t.Errorf("Title different after change")
   }
}
      
      



:





go test -v -run TestGetInstance
=== RUN   TestGetInstance
--- PASS: TestGetInstance (0.00s)
PASS
ok      main/Singleton  0.310s
      
      



! , , . , , :





package Singleton

import (
   "fmt"
   "strconv"
   "sync"
   "testing"
)

func TestSecondGetInstance(t *testing.T) {
   s1 := GetInstance()
   s2 := GetInstance()

   var w sync.WaitGroup

   for i := 0; i < 3000; i++ {
      j := i
      w.Add(1)
      go func() {
         t := "title_" + strconv.Itoa(j)
         s1.SetTitle(t)
         w.Done()
      }()
      w.Add(1)
      go func() {


         t2 := "title_2_" + strconv.Itoa(j)
         s2.SetTitle(t2)
         w.Done()
      }()
   }

   fmt.Println(s1.GetTitle())
   fmt.Println(s2.GetTitle())
}
      
      



:





go test -v -run TestSecondGetInstance
=== RUN   TestSecondGetInstance
title_2998
title_2_2999
      
      



3000 , . , . , - , . ?





-ra



, . Golang, . .





. , Singleton. . , . , , : . , , . Go : sync.Mutex



sync.RWMutex



. :





// declaration defined type
type singleton struct {
   title string
   sync.RWMutex
}

// Setter for singleton variable
func (s *singleton) SetTitle(t string) {
   s.Lock()
   defer s.Unlock()
   s.title = t
}

// Getter singleton variable
func (s *singleton) GetTitle() string {
   s.RLock()
   defer s.RUnlock()
   return s.title
}
      
      



, :





go test -v -run TestSecondGetInstance
=== RUN   TestSecondGetInstance
--- PASS: TestSecondGetInstance (0.00s)
PASS
      
      



Singleton



Golang



.





?

  1. .





  2. .





  3. .





?

  1. . // , .





  2. .





  3. Golang. , .





  4. mock-. , . dummy.





Singleton — , , . , , , . - — Singleton, . (SRP), , . Singleton, . Singleton — , .





, , . - -, , .





. Golang. .

Alex Versus. !








All Articles