Ce face sync/atomic.Int64.And
Un număr întreg poate ține mai multe steaguri da/nu, câte unul pe fiecare bit. n.Or(masca) aprinde biții din mască (n |= masca), iar n.And(^masca) îi stinge (n &= ^masca). Ambele se fac atomic și returnează valoarea dinainte de modificare.
Pentru că primești valoarea veche, afli dacă tu ai fost cel care a aprins un bit: vechi & masca == 0. Metodele există și pentru Int32, Uint32, Uint64, Uintptr și ca funcții (atomic.OrInt64, atomic.AndInt64).
Parametri
| Parametru | Descriere |
|---|---|
mask |
Masca de biți: pentru Or, biții de aprins; pentru And, biții de păstrat. |
Ce returnează
Valoarea veche (de dinainte de operație).
Exemple
Exemplul 1: Permisiuni ca steaguri pe biți
package main
import (
"fmt"
"sync/atomic"
)
const (
Citire int64 = 1 << iota // 1
Scriere // 2
Stergere // 4
)
func main() {
var drepturi atomic.Int64
vechi := drepturi.Or(Citire | Scriere)
fmt.Printf("Or: vechi=%03b nou=%03b\n", vechi, drepturi.Load())
vechi = drepturi.Or(Stergere)
fmt.Printf("Or: vechi=%03b nou=%03b\n", vechi, drepturi.Load())
vechi = drepturi.And(^Scriere) // stinge bitul de scriere
fmt.Printf("And: vechi=%03b nou=%03b\n", vechi, drepturi.Load())
fmt.Println("Poate scrie:", drepturi.Load()&Scriere != 0)
fmt.Println("Poate șterge:", drepturi.Load()&Stergere != 0)
}
Rezultat
Or: vechi=000 nou=011
Or: vechi=011 nou=111
And: vechi=111 nou=101
Poate scrie: false
Poate șterge: true
Exemplul 2: Etape bifate de mai mulți lucrători
Fiecare lucrător aprinde bitul etapei lui. Din valoarea veche, exact un lucrător află că el a bifat ultima etapă și trimite notificarea.
package main
import (
"fmt"
"sync"
"sync/atomic"
)
func main() {
etape := []string{"plată", "stoc", "factură", "livrare"}
toate := int64(1)<<len(etape) - 1
var gata atomic.Int64
var notificari atomic.Int32
var wg sync.WaitGroup
for i := range etape {
wg.Go(func() {
vechi := gata.Or(1 << i)
if vechi|1<<i == toate { // eu am bifat ultima etapă
notificari.Add(1)
}
})
}
wg.Wait()
fmt.Printf("Etape terminate: %04b\n", gata.Load())
fmt.Println("Comanda completă:", gata.Load() == toate)
fmt.Println("Notificări „comandă gata” trimise:", notificari.Load())
}
Rezultat
Etape terminate: 1111
Comanda completă: true
Notificări „comandă gata” trimise: 1
Greșeli frecvente
- Scrii
n.And(masca)când vrei să stingi biții din mască.Andpăstrează doar biții din mască; pentru stingere dai masca negată:n.And(^masca). - Folosești valoarea returnată ca valoare nouă.
AndșiOrreturnează valoarea veche; pentru cea nouă apeleazăLoad().
Comenzi înrudite
sync/atomic.Int64: Un int64 cu operații atomice ca metode (Add, Load, Store, Swap); varianta recomandată pentru contoare între goroutine.sync/atomic.Bool: O valoare true/false citită și scrisă atomic; bună pentru steaguri ca „închis”, „pregătit” sau „rulează deja”.