Ce este
Șablonul Singleton se asigură că un tip are exact o singură instanță în tot programul și oferă tuturor același punct de acces la ea. Singleton-uri tipice: o configurație, un pool de conexiuni, un logger.
Unealta din Go pentru asta este sync.Once: codul de inițializare din once.Do() rulează exact o singură dată, chiar și atunci când multe goroutine îl cer în același timp.
Exemplu: o singură configurație pentru toți
Configurația este încărcată la primul apel GetConfig() și niciodată din nou. Fiecare apelant primește același pointer.
Încărcare o singură dată cu sync.Once
Linia „se încarcă configurația” este afișată o singură dată, deși GetConfig() este apelată de două ori — iar a == b dovedește că ambii apelanți dețin aceeași instanță.
Ieșire: program Go și rezultatul capturat
package main
import (
"fmt"
"sync"
)
type Config struct {
AppName string
}
var (
once sync.Once
instance *Config
)
func GetConfig() *Config {
once.Do(func() {
fmt.Println("se încarcă configurația (se întâmplă o singură dată)")
instance = &Config{AppName: "PromptCookbook"}
})
return instance
}
func main() {
a := GetConfig()
b := GetConfig()
fmt.Println("aplicație:", a.AppName)
fmt.Println("aceeași instanță:", a == b)
}
Când să îl folosești
Folosește-l atunci când chiar trebuie să existe un singur exemplar din ceva: o singură configurație încărcată, un singur pool de conexiuni, un singur cache — iar crearea lui este costisitoare sau duplicatele ar intra în conflict.
Renunță la el atunci când poți pur și simplu să creezi valoarea în main() și să o transmiți celor care au nevoie de ea. Transmiterea deschisă a dependențelor este mai clară decât accesul global — singleton-ul este ultima soluție, nu prima.
Avantaje și dezavantaje
Avantaje: instanță unică garantată; creare leneșă la prima utilizare; siguranță cu multe goroutine prin sync.Once.
Dezavantaje: este o variabilă globală deghizată — dependențele ascunse fac codul mai greu de urmărit; testele nu îl pot înlocui ușor cu o variantă falsă; folosirea în exces duce la programe încurcate.