Used to ensure that an action is executed only once, it can be used in singleton mode, such as initializing configuration. We know that the init() function will only be executed once, but it is
main()
The function is executed before. If you want to run an action only once during the code execution, you can use it., Let’s introduce how to use it.
Let’s take a look at the following code:
package main import ( "fmt" "sync" ) func main() { var num = 6 var once add_one := func() { num = num + 1 } minus_one := func() { num = num - 1 } (add_one) ("The num: %d\n", num) (minus_one) ("The num: %d\n", num) }
Execution results:
The num: 7
The num: 7
Type provides a
Do
Method, Do method only accepts one parameter, and the parameter type must befunc()
, that is, a function without parameter declaration and result declaration.
Do
The method will only execute the function passed in when it is called for the first time, and will only execute once, and will not execute other functions. In the above example, even if the function passed in is different, only the function passed in the first time will be executed. If there are multiple functions that are executed only once, one needs to be assigned to each functionValue of type:
func main() { var num = 6 var once1 var once2 add_one := func() { num = num + 1 } minus_one := func() { num = num - 1 } (add_one) ("The num: %d\n", num) (minus_one) ("The num: %d\n", num) }
Type is a structure type, and one is named
done
ofuint32
Type field, and a mutex lockm
。
type Once struct { done uint32 m Mutex }
done
The value of the field can only be 0 or 1.Do
After the first call of the method is completed,done
The value of 1 becomes 1. The done value uses four bytesuint32
The reason for type is to ensure that the operation on it is a "atomic operation", by callingatomic.LoadUint32
The function gets its value. If it is 1, it will return directly and the function will not be executed.
If 0, the Do method will lock the field m immediately. If there is no lock here, multiplegoroutine
When executing Do method at the same time, it is determined that it is 0, and the function will be executed.Once
It is concurrently safe.
After locking, it will be checked againdone
The value of the field, if the condition is met, execute the passed function and operate the function atomicallyatomic.StoreUint32
Willdone
The value of 1 is set to 1.
Here is the source code of Once:
func (o *Once) Do(f func()) { if atomic.LoadUint32(&) == 0 { (f) } } func (o *Once) doSlow(f func()) { () defer () if == 0 { defer atomic.StoreUint32(&, 1) f() } }
The source code is very concise and very similar to the singleton pattern in the GoF design pattern.
This is the end of this article about Go concurrent programming. For more related Go language content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!