Ce face sync.OnceValue
sync.OnceValue(f) primește o funcție care calculează ceva și returnează o funcție nouă. La primul apel rulează f și ține minte rezultatul; la apelurile următoare returnează direct rezultatul păstrat. Este cel mai simplu mod de a face o valoare globală „leneșă”, calculată abia când e nevoie de ea.
sync.OnceValues(f) face același lucru pentru funcții cu două rezultate, cel mai des (valoare, error): și eroarea este păstrată și returnată la fiecare apel. Ambele sunt generice: tipul rezultatului este dedus din f.
Parametri
| Parametru | Descriere |
|---|---|
f |
Funcția care calculează valoarea (sau perechea de valori). |
Ce returnează
O funcție care returnează mereu același rezultat (sau aceeași pereche).
Exemple
Exemplul 1: Tabel calculat o singură dată
package main
import (
"fmt"
"sync"
)
var numerePrime = sync.OnceValue(func() []int {
fmt.Println("(calculez numerele prime până la 50)")
var prime []int
for n := 2; n <= 50; n++ {
prim := true
for _, p := range prime {
if n%p == 0 {
prim = false
break
}
}
if prim {
prime = append(prime, n)
}
}
return prime
})
func main() {
fmt.Println("Primele 5:", numerePrime()[:5])
fmt.Println("Câte sunt:", len(numerePrime()))
}
Rezultat
(calculez numerele prime până la 50)
Primele 5: [2 3 5 7 11]
Câte sunt: 15
Exemplul 2: OnceValues cu valoare și eroare
Citirea portului se face o singură dată; și eroarea este păstrată.
package main
import (
"fmt"
"strconv"
"sync"
)
func citestePort(text string) func() (int, error) {
return sync.OnceValues(func() (int, error) {
fmt.Println("(citesc portul din configurare)")
return strconv.Atoi(text)
})
}
func main() {
port := citestePort("8080")
for range 2 {
p, err := port()
fmt.Println("port:", p, "eroare:", err)
}
gresit := citestePort("opt mii")
for range 2 {
_, err := gresit()
fmt.Println("eroare:", err)
}
}
Rezultat
(citesc portul din configurare)
port: 8080 eroare: <nil>
port: 8080 eroare: <nil>
(citesc portul din configurare)
eroare: strconv.Atoi: parsing "opt mii": invalid syntax
eroare: strconv.Atoi: parsing "opt mii": invalid syntax
Greșeli frecvente
- Modifici slice-ul sau map-ul returnat de
OnceValue. Toți apelanții primesc același obiect, deci modificarea se vede peste tot; copiază-l dacă trebuie schimbat.
Comenzi înrudite
sync.Once: Garantează că o funcție rulează o singură dată, chiar dacă Do este apelat de multe goroutine (inițializare leneșă).sync.OnceFunc: Returnează o funcție care rulează f doar la primul apel; apelurile următoare nu fac nimic.