一、前言
有时,我们需要让某个函数只执行一次,那么如何来保证那?一般是我们自己写个原子变量来控制函数是否已经执行过,这样可行,但是需要我们自己实现这非业务逻辑的功能,其实go SDK中提供了sync.once()方法,帮我们封装了这层操作。
二、自己实现函数只执行一次
如下代码,我们在main方法内通过循环语句开启新goroutine异步调用sayHello()方法,运行后我们会看到输出100句 hello,world。
func sayHello() {
fmt.Println("hello,world")
}
func main() {
for i := 0; i < 100; i++ {
go sayHello()
}
// go中main goroutine退出,则整个进程就退出
//所以这里我们简单休眠,等待子goroutine执行完毕
time.Sleep(time.Minute)
}
如果我们想要实现虽然调用100次sayHello()但是只输出一条hello,world,一个可能的实现是这样的:
var flag int32
func sayHello() {
if atomic.CompareAndSwapInt32(&flag, 0, 1) {
fmt.Println("hello,world")
}
}
func main() {
for i := 0; i < 100; i++ {
go sayHello()
}
// go中main goroutine退出,则整个进程就退出
//所以这里我们简单休眠,等待子goroutine执行完毕
time.Sleep(time.Minute)
}
如上代码,我们创建了一个flag变量,然后再sayHello方法内使用CAS设置flag的值,由于flag的初始化值为0,所以当多个goroutine执行CAS时,只有一个goroutine可以把flag的值从0设置为1