Ce face sync/atomic.Value
atomic.Value păstrează o valoare de tip any. Store o înlocuiește dintr-o dată, iar Load returnează ultima valoare salvată (sau nil dacă nu s-a salvat nimic). Cititorii nu se blochează niciodată, deci este potrivit pentru date citite foarte des și schimbate rar, de exemplu o configurare reîncărcată fără oprirea serverului.
Toate valorile salvate trebuie să aibă același tip concret; altfel Store se oprește cu panică. Store(nil) nu este permis. Valoarea salvată nu trebuie modificată după Store: creezi o valoare nouă și o salvezi pe ea.
Din Go 1.19, atomic.Pointer[T] face același lucru cu tipuri verificate de compilator și este de preferat în cod nou.
Ce returnează
Load: valoarea (any) sau nil. Swap: valoarea veche. CompareAndSwap: dacă a înlocuit.
Exemple
Exemplul 1: Configurare reîncărcată din mers
package main
import (
"fmt"
"sync/atomic"
)
type Config struct {
Mesaj string
Limita int
}
var config atomic.Value
func main() {
fmt.Println("Înainte de Store:", config.Load())
config.Store(Config{Mesaj: "Bun venit!", Limita: 100})
c := config.Load().(Config)
fmt.Println("Configurare:", c.Mesaj, c.Limita)
// reîncărcare: valoare nouă, salvată dintr-o dată
config.Store(Config{Mesaj: "Reduceri de Black Friday!", Limita: 500})
c = config.Load().(Config)
fmt.Println("După reîncărcare:", c.Mesaj, c.Limita)
}
Rezultat
Înainte de Store: <nil>
Configurare: Bun venit! 100
După reîncărcare: Reduceri de Black Friday! 500
Exemplul 2: Tipul trebuie să rămână același
Un Store cu alt tip se oprește cu panică; o recuperăm ca să vedem mesajul.
package main
import (
"fmt"
"sync/atomic"
)
func main() {
var v atomic.Value
v.Store("Iași")
vechi := v.Swap("Cluj")
fmt.Println("Swap:", vechi, "->", v.Load())
defer func() {
fmt.Println("Panică:", recover())
}()
v.Store(42)
}
Rezultat
Swap: Iași -> Cluj
Panică: sync/atomic: store of inconsistently typed value into Value
Greșeli frecvente
- Salvezi un map sau un slice și apoi îl modifici. Cititorii văd modificările fără sincronizare; construiește un map nou și salvează-l pe el.
- Faci
v.Load().(Config)înainte de primulStore:Loadreturneazănilși conversia se oprește cu panică. Salvează o valoare inițială sau foloseștec, ok := v.Load().(Config).
Comenzi înrudite
sync/atomic.Pointer: Un pointer *T citit și înlocuit atomic, cu tip verificat la compilare; varianta modernă a lui atomic.Value.sync.RWMutex: Lacăt pentru citire și scriere: mai mulți cititori pot lucra deodată (RLock), dar un scriitor lucrează singur (Lock).sync.Once: Garantează că o funcție rulează o singură dată, chiar dacă Do este apelat de multe goroutine (inițializare leneșă).