Once: a simple but not simple concurrency primitive

Once can be used to execute an action only once, and is often used in the initialization scenario of a singleton object.

Usage scenarios of Once

sync.Once only exposes one method Do. You can call the Do method multiple times, but the f parameter will only be executed when the Do method is called for the first time. Here f is a function with no parameters and no return value.

func main() {
    
    
    var once sync.Once

    // 第一个初始化函数
    f1 := func() {
    
    
        fmt.Println("in f1")
    }
    once.Do(f1) // 打印出 in f1

    // 第二个初始化函数
    f2 := func() {
    
    
        fmt.Println("in f2")
    }
    once.Do(f2) // 无输出
}

Once is often used to initialize singleton resources, or concurrent access to shared resources that only need to be initialized once, or to initialize test resources once during testing.

syncOnce.go

package main

import (
    "fmt"
    "sync"
)

var once sync.Once

type single struct {
    
    
}

var singleInstance *single

func getInstance() *single {
    
    
    if singleInstance == nil {
    
    
        once.Do(
            func() {
    
    
                fmt.Println("Creating single instance now.")
                singleInstance = &single{
    
    }
            })
    } else {
    
    
        fmt.Println("Single instance already created.")
    }

    return singleInstance
}

main.go

package main

import (
    "fmt"
)

func main() {
    
    

    for i := 0; i < 30; i++ {
    
    
        go getInstance()
    }

    // Scanln is similar to Scan, but stops scanning at a newline and
    // after the final item there must be a newline or EOF.
    fmt.Scanln()
}

Reference materials:

Singleton pattern in golang

Guess you like

Origin blog.csdn.net/csdniter/article/details/111152388