使用 sync.Once 可以保证一个函数只会被执行一次,如果需要让该函数执行两次,可以通过以下方式实现:
- 使用 sync.Mutex 来控制 once 对象的状态,使其重新变为未执行过状态。
var once sync.Once
var mu sync.Mutex
func doTwice() {
mu.Lock()
defer mu.Unlock()
// 强制设置 once 状态为未执行过
once = sync.Once{}
once.Do(func() {
fmt.Println("Hello")
})
once.Do(func() {
fmt.Println("World")
})
}
- 直接使用 reflect 修改 once 对象的状态,使其重新变为未执行过状态。
import (
"reflect"
"sync"
)
func doTwice() {
once := &sync.Once{}
once.Do(func() {
fmt.Println("Hello")
})
// 通过反射修改 once 对象的 done 字段
v := reflect.ValueOf(once).Elem()
v.FieldByName("done").SetBool(false)
once.Do(func() {
fmt.Println("World")
})
}
注意:这两种方法都是 hack 的做法,不建议在生产环境中使用。最好的解决方案是将需要执行多次的代码抽取成函数,并在需要执行多次的地方手动调用该函数。