I've been tempted to reset the sync.Once inside the function, but I believe there's a subtle bug -- I'd be very interested to know if my understanding is incorrect.
When Do() is called for the first time, it can aquire a mutex, and defers the unlocking until after the supplied function has completed. If you reset the state of the Once inside the supplied function, the mutex state gets reset as well -- meaning that the defer would unlock a mutex that hadn't ever been locked. Calling the Do() *again* with in the supplied function is...asking for more problems, and starts getting a bit harder to reason about than I care to try on a sunday evening. It'd be much better to use something like https://godoc.org/golang.org/x/sync/singleflight to deduplicate calls -- or have a secondary mutex that gets aquired to occasionally reset the once. On Sunday, November 19, 2017 at 4:24:41 PM UTC-8, Carl Mastrangelo wrote: > > Hi gophers, > > I was playing around with a puzzle trying to break the sync package and > found something cool. Can you think of a definition for f that causes > once.Do to execute the argument more than once? > > > package main > > import ( > "sync" > ) > > func main() { > var once sync.Once > var f = // ... > > once.Do(f) > } > > > HIGHLIGHT BELOW FOR ANSWER > > > package main > > import ( > "fmt" > "sync" > ) > > func main() { > var once sync.Once > var f func() > times := 9 > f = func() { > if times == 0 { > return > } > times-- > fmt.Println("Called") > oldonce := once > *&once = sync.Once{} > once.Do(f) > once = oldonce > > } > once.Do(f) > } > > HIGHLIGHT ABOVE FOR ANSWER > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.