Die Feinheiten der Singleton-Implementierung in Golang

Hallo Freunde.





Mein Name ist Alex Versus und heute werden wir uns das Singleton- Muster ansehen , eine Implementierung in der Golang- Sprache .





Was ist der Sinn?

Singleton - bezieht sich auf generative Muster. Garantiert:





  • dass die Klasse / der Typ nur eine Instanz hat





  • bietet einen globalen Zugangspunkt dazu.





Welches Problem löst es?

Lassen Sie uns über das Problem sprechen, das die Vorlage löst. Ein Einzelgänger löst zwei Probleme gleichzeitig und verstößt gegen das Single Responsibility Principle (SRP) :





  1. Stellt sicher, dass es eine einzelne Instanz des Objekts gibt. Dies ist nützlich, um auf eine gemeinsam genutzte Ressource wie eine Datenbank zuzugreifen oder um einen einzelnen Mechanismus zum Ändern einer Eigenschaft zu implementieren, z. B. den Schallpegel in einem Equalizer.

    Stellen wir uns vor, wir haben eine Art Objekt und nach einer Weile erstellen Sie ein anderes, möchten aber kein neues, sondern bereits erstelltes Objekt erhalten. Dieses Verhalten kann nicht mit Standardwerkzeugen wie dem Konstruktor in objektorientierten Sprachen erstellt werden.





  2. Stellen Sie einen globalen Hotspot bereit. Bitte beachten Sie, dass dies nicht nur eine globale Variable ist, über die Sie ein bestimmtes Objekt erreichen können. Die globale Variable schützt Sie nicht vor dem Überschreiben des erstellten Objekts.





Entwickler rufen häufig Lonely-Objekte auf, die nur eine Aufgabe ausführen, wie oben beschrieben. Dies ist ein Missverständnis des Musters.





Was ist die Lösung in Golang?

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





Singleton-Klassendiagramm
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