Seluk-beluk implementasi Singleton di Golang

Hai teman.





Nama saya Alex Versus dan hari ini kita akan melihat pola Singleton , sebuah implementasi dalam bahasa Golang .





Apa gunanya?

Singleton - mengacu pada pola generatif. Terjamin:





  • bahwa kelas / jenis hanya memiliki satu contoh





  • menyediakan jalur akses global ke sana.





Masalah apa yang dipecahkannya?

Mari kita bicara tentang masalah yang dipecahkan oleh template. Seorang penyendiri memecahkan dua masalah sekaligus, melanggar Prinsip Tanggung Jawab Tunggal (SRP) :





  1. Memastikan bahwa ada satu contoh objek. Ini berguna untuk mengakses sumber daya bersama, seperti database, atau saat mengimplementasikan mekanisme tunggal untuk mengubah properti, seperti level suara dalam equalizer.

    Mari kita bayangkan bahwa kita memiliki beberapa jenis objek dan setelah beberapa saat Anda membuat yang lain, tetapi Anda tidak ingin menerima objek baru, tetapi sudah dibuat. Perilaku ini tidak dapat dibuat menggunakan alat standar seperti konstruktor dalam bahasa berorientasi objek.





  2. Sediakan hotspot global. Harap dicatat bahwa ini bukan hanya variabel global yang dapat digunakan untuk menjangkau objek tertentu. Variabel global tidak melindungi Anda dari menimpa objek yang dibuat.





Pengembang sering menyebut objek Lonely yang hanya melakukan satu tugas, seperti yang diuraikan di atas. Ini adalah kesalahpahaman tentang polanya.





Apa solusinya di Golang?

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





Diagram kelas tunggal
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