SoFunction
Updated on 2025-03-05

Singleton pattern explanation and code examples of Go design pattern

Go Single casePattern explanation and code examples.

Single caseIt is a creative design pattern that allows you to ensure that a class has only one instance and provides a global node to access that instance.

Singletons have the same advantages and disadvantages as global variables. Although they are very useful, they can destroy the modularity of the code.

In some other contexts, you cannot use a singleton-dependent class. You will also have to use a singleton class. In most cases, this restriction occurs when creating unit tests.

Concept example

Typically, singleton instances are created when the structure is first initialized. To achieve this, we define aget­InstanceGet the instance method. This method will be responsible for creating and returning singleton instances. After creation, each callget­InstanceThe same singleton instance will be returned.

Is there anything to pay attention to in coroutines? Whenever multiple coroutines want to access an instance, the singleton structure must return the same instance. Because of this, the implementation of singleton design patterns is prone to errors. The example below shows the correct way to create a singleton.

Some notable points:

  • There will benilCheck, make suresingle­InstanceSingleton instances are empty at the beginning. This is to prevent every callget­InstanceAll methods are used to perform huge locking operations. If the inspection fails, it meanssingle­InstanceThe field has been populated.
  • single­InstanceThe structure will be created during locking.
  • There will be another one after the lock is obtainednilexamine. This is to ensure that even if multiple coroutines bypass the first check, only one single instance can be created. Otherwise, all coroutines will create their own singleton structure instances.

:Single case

package main
import (
    "fmt"
    "sync"
)
var lock = &{}
type single struct {
}
var singleInstance *single
func getInstance() *single {
    if singleInstance == nil {
        ()
        defer ()
        if singleInstance == nil {
            ("Creating single instance now.")
            singleInstance = &single{}
        } else {
            ("Single instance already created.")
        }
    } else {
        ("Single instance already created.")
    }
    return singleInstance
}

:Client code

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.
    ()
}

:Execution results

Creating single instance now.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.
Single instance already created.

Another example

  • initfunction

We caninitCreate a singleton instance in the function. This only applies when the instance's early initialization work has been determined.initThe function will only be called once in each file in the package, so we can be sure that it will only create one instance.

Only once will be performed. You can view the following code:

:Single case

package main
import (
    "fmt"
    "sync"
)
var once 
type single struct {
}
var singleInstance *single
func getInstance() *single {
    if singleInstance == nil {
        (
            func() {
                ("Creating single instance now.")
                singleInstance = &single{}
            })
    } else {
        ("Single instance already created.")
    }
    return singleInstance
}

:Client code

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.
    ()
}

:Execution results

Creating single instance now.
Single instance already created.
Single instance already created.

This is the article about the singleton pattern explanation and code examples of Go design pattern. For more related Go singleton pattern content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!